메뉴 건너뛰기

조회 수 2898 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부

1. Chrome 개발자도구 Network 탭

크롬에서 F12키나 Ctrl+Shift+I 혹은 메뉴의 '도구 더 보기'에서 열 수 있는 개발자도구는 아주 강력하다. HTML dom 탐색은 물론 javascript나 css 소스를 탐색하고 수정할 수 있을뿐 아니라 수정해 곧바로 적용해 볼 수 있다. 이번 포스트에서 주로 사용하는 Network탭에서는 실시간으로 Request / Response 정보를 확인 수 있다.



각 요청이 시작되기 전/후를 스크린샷으로 남기는 기능과 원하는 요청만 표시하는 필터같은 유용한 기능도 있다. 다양한 기능을 한번씩 사용해 보면 많은 도움이 된다.




2. Jsoup로 네이버 검색어 자동완성 목록 얻어오기

네이버 검색창에 단어를 입력했을 때 나오는 검색어 자동완성 목록을 Jsoup로 얻어보자.


이거.



먼저 크롬의 개발자 도구를 열어 두고 네이버 검색창에 단어를 입력해 보자. 키를 누를 때마다 Request/Response가 감지된다.





검색창에 입력할 때마다 특정 URL로 get Request가 있다는 사실을 알 수 있다. Response 탭을 이용해 Response를 확인해 보자.




뭔가 이상하다. 이건 무슨 코드일까?




다시 Request의 헤더를 보자. _callback 파라미터와 Response의 첫 부분이 같다는 사실을 알 수 있다. 


 


또한 window라는 Javascript Object와 __jindo_callback... 형식이 함수와 유사하다는 점을 통해


 클라이언트에서 _callback 파라미터로 함수의 이름을 전달하고, 

 서버에서 _callback 파라미터로 전달된 함수의 파라미터로 '결과' Json을 적어 반환해 

 클라이언트에서 결과 '문자열'을 실행하거나 정의하는 형식이라고 추측할 수 있다. 


그림으로 표현하면 아래와 같다.



그야말로 막연한 추측이다. 하지만 _callback 파라미터를 조정해 볼 필요는 있다. 한번 시도해 보자.



Chrome 확장프로그램 Advanced REST client로 테스트한 결과.

_callback 파라미터를 공백으로 요청하자 Json 형태로 결과를 얻을 수 있었다.



개인적인 경험상, 개발의 편의성 때문인지 HTML 코드를 그대로 반환하는 사이트가 가장 많고, 그 다음으로 위와 같이 Json과 다른 형식의 코드가 섞인 경우가 많았다. Json 포맷으로 Response가 오는 정직한 경우는 별로 없으니 얻어낸 문자열을 다시 가공하거나 위의 경우처럼 파라미터를 조정해 볼 필요가 있다.



아무튼, 위에서 알아낸 URL과 Request 헤더들을 이용해 Jsoup로 네이버의 검색어 자동완성 목록을 얻어내 보자.


String q = "스칼라"; // 검색어

Document doc = Jsoup.connect("https://ac.search.naver.com/nx/ac")
.header("origin", "http://www.naver.com")
.header("referer", "https://www.naver.com/")
.header("accept-encoding", "gzip, deflate, sdch, br")
.data("con", "1")
.data("_callback", "") // _callback 파라미터를 비우면 JSON이 리턴된다!
.data("rev", "4")
.data("r_enc", "UTF-8")
.data("q", q) // 임의로 몇개의 파라미터와 헤더를 생략했다.
.data("st", "100") // 각 파라미터가 무엇을 뜻하는지를 확인해 적절하게 사용하는 것도 좋지만
.data("q_enc", "UTF-8") // 비정상적인 요청으로 감지해 아이디나 아이피가 밴 될 우려도 있으므로
.data("r_format", "json") // 특별한 이유가 없다면 모두 포함하는 것이 좋다.
.data("t_koreng", "1")
.data("ans", "2")
.data("run", "2")
.ignoreContentType(true) // HTML Document가 아니므로 Response의 컨텐트 타입을 무시한다.
.get();

List<String> result = new ArrayList<>();

// org.json 라이브러리를 사용해 결과를 파싱한다.
JSONObject jsonObject = new JSONObject(doc.text());

JSONArray items = (JSONArray) ((JSONArray) jsonObject.get("items")).get(0);
for(int i=0; i<items.length(); i++) {
String item = (String) (((JSONArray) items.get(i)).get(0));
result.add(item);
}

// 얻어낸 추천 검색어 목록.
// 테스트 프로젝트의 자바 버전이 낮아 for문을 사용했다.
for(String item : result) {
System.out.println(item);
}
/*
스칼라티움 강남
스칼라티움
구글스칼라
스칼라
강남 스칼라티움
첼로 스칼라티 105
스칼라티움 상암
수원 스칼라티움
상암 스칼라티움
첼로 스칼라티
구리 스칼라티움
스칼라 동시성 프로그래밍
스칼라 월드 북스 3
스칼라 월드 북스 4
스칼라 월드 북스 5
*/


원하는 정보를 얻어냈다.(웨딩홀 이름이 가장 위라니 조금 슬프다)




이 예제에는 없었지만 XMLHttpRequest 객체를 사용하는 Request에는 'X-Requested-With' 헤더 값으로 'XMLHttpRequest'가 전송되기도 한다. 다시한번 말하지만 사이트마다 다르고 비정상적인 요청으로 간주될 수 있으니 브라우저에서 직접 헤더를 확인해 보고 Jsoup의 헤더에 똑같이 작성하는 것이 좋다.


List of Articles
번호 제목 날짜 조회 수
38 스프링(spring) 메일 발송 :: mailSender 2016.08.18 14879
37 play framework + 이클립스 초간단 개발환경 구축법 2016.12.08 12416
36 쿠키와 세션을 이용한 자동 로그인 처리 file 2018.07.04 8973
35 루씬 기본적인 검색 엔진 - 샘플 예제 file 2016.12.08 7769
34 자바 스프링프레임워크 개발환경 설정하기-1편 file 2016.08.18 6840
33 자바 스프링프레임워크 개발환경 설정하기-2편 file 2016.08.18 6490
32 검색엔진 (2) - 라이브러리: Lucene, Solr, Elasticsearch 2016.12.08 6228
31 자바 스프링, spring AOP 구현 (xml 방식) file 2016.08.18 6200
30 검색엔진 (1) - 검색엔진의 이해 2016.12.08 6032
29 [펌]자바 Crawling(크로울링) 로그인 해 긁어오기 file 2018.07.04 6005
28 [패스트캣]1. 시작하기 - 설치 file 2016.12.08 5982
27 Nutch 0.9 를 이용하여 한글 검색하기 2016.12.08 5928
26 자바 스프링, spring AOP 구현 (xml 방식) file 2016.08.18 5892
25 스프링 2.5.2 설치및 HelloWorld 출력하기 file 2016.12.06 5836
24 스프링 AOP의 주요 용어 file 2016.08.18 5829
23 solr적용시 사용법 2016.12.08 5582
22 Spring Security Basic 인증 비활성화 설정 file 2016.08.18 5556
21 스프링과 안드로이드 연동4 : (JSON으로 가져오기) file 2018.07.04 5530
20 Spring 개발을 위한 Eclipse 개발 환경 구성하기 file 2016.12.06 5431
19 Spring Framework 개요 2016.12.08 5339
Board Pagination Prev 1 2 Next
/ 2

하단 정보를 입력할 수 있습니다

© k2s0o1d4e0s2i1g5n. All Rights Reserved