ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Jsoup 웹 크롤링 , 스프링 부트 구글 지도 위도 경도 가져오기
    Project/NomadWorker 2022. 8. 11. 16:21

    제1회 한국외대 썸머 해커톤 우수상을 받은 프로젝트 "노마드 워커 "의 기능을 개발 하는데 필요했던 기능 구현의 관한 글 입니다.

     

    깃허브 :  https://github.com/HUFSummer-Hackathon/Server

     

    GitHub - HUFSummer-Hackathon/Server

    Contribute to HUFSummer-Hackathon/Server development by creating an account on GitHub.

    github.com

     

     

    특정 사이트에서 위도 경도를 주소마다 변환해서 가져오고 그것을 다시 db 에 넣는 수고 스러움을 덜고 싶었다.

     

    목표: 

    특정 장소의 위도 경도 가져오기 , 구글 맵 api 사용 안하기.

     구글지도 위도 경도 가져오기.

     

    Point

    가능하면 웹사이트에서 response body에 포함된 data 를 가져오는 방식 보다 url 쿼리 response 를 가져오는 것을 고려 한다.

     

     

    사용 기술 :

     

    Spring boot ,JPA , Hibernate

     

    build.graddle에 jsoup depndencie 추가. 웹 스파이더링을 위한 라이브러리이다.

    implementation 'org.jsoup:jsoup:1.15.2'

    + google devtoolkit  : 크롬창에서 f12 를 누르면 페이지의 구성요소를 알 수 가 있다.

     

     

    서문 & 문제점:

     

    스프링 프레임워크 라이브러리 jsoup 을 이용하여 주소 좌표변환 웹사이트에 원하는 검색 결과를 입력 하고 response 를  받는 작업을 해본다.

     

    1.

    !!! Jsoup 은 동적 웹페이지의 클롤링을 지원하지 않는다 ,    즉  html <input  을 이용하여 만든 form 에서 

        .버.튼.을 클,릭! 을 하여 원하는 정보를 가져 오는것이 불가능 하다. 만약 본인이 버튼을 클릭하여 나오는 데이터를 원한다 하면

    Selinium 을 검색하여 사용해보길 권한다.

     

    2.

    요즘 웹사이트의 경우 , 서버에 요청한 request 의 대한 response 를 잘 안보이게 숨기는 경우도 많고 (보안상의 이유로),

    Jsoup 을 단독으로 이용을 하여 response 를 원하는대로 받아오는 것이 사이트마다 다르다.

     

     

    Tip : 다음 사진의 나오는 것과 같이 구글 크롬 개발자 도구 네트워크에 있는 해더의 정보들을 확인해주자

     

    ---------------------------------------구글 개발자도구로 본  응답 ------------------------------------

     

    어떻게 하지 고민을 하다가. 

     

    구글 맵을 사용 하는 것을 생각했다. (정말 문득 구글 크롤링을 하자라고 생각이 듬)

     

    1. 구글 맵 api  

    : 비용이 든다 기각.

     

    2. 구글 맵 검색창의 원하는장소 입력이후  잠깐 나오는 url 주소를 이용한다. 

    : 이걸로 가자 

     

     

    [분석1]

    구글의 url 주소 "https://www.google.co.kr/maps/search/"

     

    /뒤의 원하는 검색 조건을 입력을 하고 검색을 하게 되면  url주소가 크롬창 기준으로 변환한다.

     

     

    검색 후  url

     

    "https://www.google.co.kr/maps/place/%(~생략~)d37.5086551!4d127.0393959?hl=ko"

     

     37.5086 , 127.039  -> 위도 경도 좌표가 url 에 포함이 되어 있다.

     

    처음 시도한 방식처럼 웹사이트에서 response data 을 가져오는 방식이 아닌 검색 결과의 따른 url redirection 의 정보를 가져오는 것이 개발측면에서 더 빠를것 같다 라는 생각을 했다.

     

     

     

    [분석2]

    구글 개발자 도구를 켜서 코드를 살펴본 결과 , <head> 테그 안 <meta content= , 에 위도 경도 좌표가 나오는 것을 확인 했다.

     

     

     

    [구현]

    코드 짜자.

     

    1.DTo

    package hackathon.nomadworker.dto;
    
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    
    public class DownloadDtos {
    
        @Data
        @AllArgsConstructor
        public static class ResultResponse<T> {
            private String message;
            private int status;
            private T data;
        }
    
        @Data
        public static class DownloadRequest
        {
            private String address;
        }
    
        @Data
        public static class DownloadResponse
        {
            private float lati;
            private float longi;
    
            public DownloadResponse(float lati, float longi) {
                this.lati = lati;
                this.longi = longi;
            }
        }
    
    
    
    
    }
    

    2. url 속 정보 추출 

    package .....api;
    import .....dto.DownloadDtos.*;
    
    import lombok.Data;
    import lombok.RequiredArgsConstructor;
    import org.jsoup.Connection.*;
    import org.jsoup.select.Elements;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RestController;
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import javax.validation.Valid;
    import java.io.IOException;
    
    
    @RequiredArgsConstructor
    @RestController
    public class PlaceDownloadApiController
    {
    
        @PostMapping(value="/api/download" , produces = "application/json;charset=UTF-8")
        public ResultResponse userPost(@Valid @RequestBody DownloadRequest request)
        {
    
            String url =  "https://www.google.co.kr/maps/search/";
            String searchaddr = request.getAddress();
            try {
                Response res = Jsoup.connect(url+request.getAddress()).followRedirects(true).execute();
    
                Document doc = res.parse();
                Elements metaTags = doc.getElementsByTag("meta");
                String linkOrigin = metaTags.get(10).attr("content");
    
    
                int s = linkOrigin.indexOf("=");
                int l = linkOrigin.indexOf("%");
                String longi =linkOrigin.substring(s+1,l);
    
                s = linkOrigin.indexOf("C");
                l = linkOrigin.indexOf("&");
                String lati =linkOrigin.substring(s+1,l);
    
                return new ResultResponse("ok",200,longi +":"+lati);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
    
    
    
    
        }
    
    
    
    
    }

     

     

    - 주요 코드 설명:

    1. 주소 창 redirects 를 따라가게 connect 을 해준다.     -> followRedirects(true)

     

        Response res = Jsoup.connect(url+request.getAddress()).followRedirects(true).execute();

     

    2. 파싱 . f12 헤더를 보면  meta tag , content 라는 부분에 우리가 원하는 위도 경도 좌표가 있다 . 

               Document doc = res.parse();
                Elements metaTags = doc.getElementsByTag("meta");
                String linkOrigin = metaTags.get(10).attr("content");

     

     

     

     

    결과 :    Request body "address" 에 구글 지도에서 검색했던 것 과 같은 키워드를 입력해본다.

     

    구글지도의 장소 명칭으로 쳤을때 나오는&nbsp; 결과 ,&nbsp; address = "서울 시청"
    주소를 통한 검색 결과

     

     

     

     

    이후 성능 개선 필요한점 .

    1.

    구글 맵에서 여러가지의 장소를 결과로 보여주면 meta data content 10 번째에 우리가 원하는 위도 경도 좌표가 없다.

    2. 의존성 문제 ,,, 구글에서 정보를 제공하는 방식이 바귀면 , 코드가 안돌아 갈 수 도 있다.

     

     

Designed by Tistory.