Loading...

Spring/Blog-V2 / / 2022. 3. 31. 09:12

스프링 56강. 웹 크롤링

반응형

 

프로젝트를 만들다가 데이터가 필요하면

첫 번째로 API를 찾아봐야 한다.

 

 

 

웹 크롤링을 방지하기 위해 네이버에서 제공해주는 API가 많이 있다.

다른 사이트에서도 API를 제공해주는 곳이 있기 때문에

첫 번째로는 API를 찾아봐야 한다.

 

API가 없다면 실제 사이트에 검색을 해서 데이터를 찾아본다.

최초 URL 주소에는 모든 데이터들이 다운로드 되어있지 않은 페이지가 있을 수 있다.

이런 페이지는 fetch로 다운 받아서 CSR 그림을 그린다.

 

 

내가 최초 URL로 데이터를 받으려고 하면

그 사이트가 fetch로 다운 받은 데이터까지 나오지 않는 것이다.

 

이때 CSR로 그려진 데이터까지 다운 받기 위해서는 두 가지 방법이 있다.

 

첫째. wait 사용

 

해당 사이트가 fetch 다운로드가 다 끝나지 않았기 때문에 완성되지 않은 그림이 받아진 것이니까

요청한 후 5초 정도 wait를 걸어두었다가 다운 받으면 데이터까지 받을 수 있다.

 

둘째로 wait보다 더 간편한 방법이 있다.

 

어차피 내부적으로 fetch를 할 거니까

F12를 눌러서 네트워크를 보면 무조건 다 나와있다.

네트워크 창에서 Ctrl + R 해서 보면 모든 요청 데이터들이 있는데

보통 쿼리 스트링으로 요청하니까 쿼리 스트링을 사용한 요청을 살펴보자.

 

 

얘를 인터넷 주소창에 검색해보면

주소에 제주시 식당이 찍힌 것만 봐도 fetch로 데이터를 다 받아온 것을 확인할 수 있다.

 

 

api를 제공해주진 않지만 얘들도 내부적으로 fetch 해서 json으로 받은 데이터이기 때문에

다 긁어올 수 있다.

 

RestTemplate는 httpURLConnection보다 쉽게 바로 다운 받을 수 있다.

이렇게 쉽게!

 

RestTemplate rt = new RestTemplate( );
String body = rt.getForObject("다운받을 주소", String.class);

 

이 주소를 rt.getForObject의 주소 자리에 넣어주면

데이터를 다운 받을 수 있다.

 

주소를 넣어줄 때 query의 밸류 값이 인코딩 되어 들어가는 부분에

내가 원하는 검색어를 넣어주면 된다.

 

 

잘 받아진다.

 

RestTemplate에 파싱 할 오브젝트 타입(String.class)을 걸어주기만 하면

RestTemplate가 다 파싱 해준다.

 


 

내가 날씨가 궁금하면 데이터를 어디서 받아와야 할까?

날씨 데이터는 공공데이터로 받아와도 되지만

크롤링해오면 빠르겠다.

 

날씨 검색을 해보면 주소창에 get요청 주소가 남아있다.

이 주소를 getForObject에 넣어줘 보자.

 

 

 

데이터를 잘 다운 받아오긴 했지만

다운 받은 데이터는 json이 아닌데 어떻게 파싱 할까?

 

애초에 json으로 내부적으로 통신하는 애들은 파싱 하기 쉬운데

html을 그대로 주면 더 힘들다.

 

내가 필요한 건 6도라는 숫자인데 브라우저에서

숫자 위에 우클릭하여 검사해보면

 

딱 얘만 필요하다.

 

 

 

얘는 documentQuerySelector로 찾을 수 있겠다.

 

 

자바에서는 이게 안되니까 jsoup라는 라이브러리를 다운로드하여준다.

jsoup는 자바로 html을 파싱 하는 라이브러리이다.

 

https://mvnrepository.com/artifact/org.jsoup/jsoup/1.14.3

 

Gradle을 복사해서 build.gradle 파일의 dependencies 안에 추가해주기만 하면 된다.

 

 

추가해주고 오른쪽 아래 다운로드가 끝나면 이제 jsoup를 사용해보자.

jsoup를 쓰면 좋은 게 RestTemplate를 사용하지 않고

Jsoup.connect("주소").get( )으로 바로 다운로드할 수 있다.

 

사용해보자.

@Test
public void 크롤() {
    try {
        Document doc = Jsoup
                .connect("https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=날씨")
                .get();
        System.out.println(doc);
        
    } catch (IOException e) {
        e.printStackTrace();
    }
}

 

doc를 출력해보니 html을 받아왔다.

 

 

다운 받은 데이터를 Document객체에 넣으면 이제 파싱이 가능하다.

아까 날씨 숫자 근처에 있던 클래스 이름으로 파싱 해주자.

 

doc.select의 리턴 타입이 Elements이다.

파싱 된 결과가 하나일 수도 있고 여러개일 수도 있기 때문이다.

 

Elements arr = doc.select(".temperature_text");

 

이 arr에 어떤 값이 저장되었는지 for each문을 돌며 콘솔에 찍어보자.

Elements는 Element들의 모임이다.

 

for (Element e : arr) {
    System.out.println(e);
}

 

여러 개의 데이터가 나온다.

 

 

찾았으니까 이제 얘들이 들고 있는 텍스트를 출력하면 끝이다.

 

for (Element e : arr) {
    System.out.println(e.text());
}

 

 

내가 html을 다운받으려면? Jsoup 사용

html을 다운받고 보니 데이터가 없다?
-> 내부적으로 fetch 요청 일어난 것
-> 이거 파싱 하는 게 더 쉽다

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 
반응형