Glacier's Daily Log

Android) 안드로이드 Jsoup로 웹크롤링 하기 (예제포함) - "데일리 브리핑 앱 개발기" 본문

Coding/Android

Android) 안드로이드 Jsoup로 웹크롤링 하기 (예제포함) - "데일리 브리핑 앱 개발기"

h__glacier_ 2021. 8. 12. 03:00
반응형

Android Jsoup 웹크롤링

안드로이드 개발시에 Java Jsoup 사용하여 웹크롤링 연습해보기


 

웹크롤링 (Web Crawling) 이란?

- 웹 페이지와 수많은 사이트들의 HTML 소스를 끌어와서 필요한 정보와 자료를 수집하는 것

 

이런 웹 크롤링은 코딩으로 할 수 있는 자동화 작업 중에 가장 쉽게 접할 수 있으며, 가장 쓸 일이 많은 작업이기도 하다.

 

보통 웹크롤링은 파이썬 BeautifulSoup4, bs4라는 라이브러리를 사용해서 많이들 접한다.

나도 이 bs4라는 라이브러리를 활용해서 웹크롤링을 해본 경험이 있고, 블로그 포스팅도 하였다.

현재 이 포스팅은 내 블로그의 누적 조회수 1위에 꾸준히 머물러 있다.

 

 

Python) 파이썬 BeautifulSoup4를 이용해 웹 크롤링 예제 만들어 보기

저번 포스팅에서는 이미지 크롤링 프로그램을 만들어 보았다. Python) 파이썬을 이용한 이미지 크롤링 프로그램 만들기 어쩌다보니 티스토리 블로그를 이용한 첫 번째 포스팅이 파이썬 코딩 관련

h-glacier.tistory.com

위 포스팅에서는 파이썬 bs4로 

현재 날씨와, 코로나 확진자, 뉴스 헤드라인, 멜론 Top10 을 크롤링하여

한번에 보여주는 유용한 프로그램을 만들어 보았다.

실제로 내 데스크탑에서도 자주 썼고, 아침에 일어나서 하루 날씨와 뉴스를 볼 때 유용하게 쓸 수 있었다.

 

하지만 내 주 개발 분야는 안드로이드 였고, 최근에 안드로이드에서 웹크롤링을 해서 위의 프로그램을 만들어보면 어떨까? 라는 생각을 하게 되었다.

그래서 찾아보니 파이썬의 bs4처럼, 안드로이드 자바에는 Jsoup 라는 라이브러리가 있는 것을 확인했다.

 

그럼 지금부터 시작해보자.


우선, 안드로이드 스튜디오를 켜고 새로운 프로젝트를 만든다.

나는 "데일리 브리핑" 이라는 앱을 만들어서, 출시까지 할 계획으로 시작했다.

현재 포스팅 시에는 이미 개발 완료 후 출시까지 한 상태이다.

 

프로젝트를 만들고, AndroidManifest.xml 에 들어간다.

웹크롤링을 위해 필요한 내용을 추가해줄 것이다.

 

<uses-permission android:name="android.permission.INTERNET" />

//application 태그 안에
 android:usesCleartextTraffic="true"

이렇게 추가해주자. 

인터넷 권한을 주는 코드와, http통신을 가능하게 해주는 코드이다.

 

그리고, gradle의 Module 수준 파일을 열어서 Jsoup 라이브러리를 implementation 시키자.

implementation 'org.jsoup:jsoup:1.13.1'

그러면 이제 Jsoup를 사용할 기초 준비는 완료 되었다.


이제 본격적으로 웹크롤링을 시작할 것이다.

시작하기전에, 자기가 크롤링 해오고 싶은 정보를 정해야한다.

 

그렇기 때문에, 시작하기 전에 내가 만들고 싶은 앱에 대해 생각해보자.

 

앱 구상해본 스케치 도안

우선, 첫번째 화면은 현재 날짜와 시간을 보여줄 것이다.

그리고 두번째 화면으로 넘어가서 본격적으로 웹크롤링을 시작한다.

1. 날씨 , 2. 코로나 신규 확진자 , 3. 주요 뉴스 헤드라인

이렇게 총 3개를 크롤링해서 보여줄 생각이다.

 

우선, 안드로이드의 Activity 구동 구조를 알아보자.

액티비티가 실행되면, onCreate 메소드에서 우리가 원하는 코드들을 돌릴 수 있게 된다.

따라서 우리는 onCreate에 앱이 실행될 때 수행하는 코드를 작성하게 되는데

이 때 우리가 작성한 코드와 UI를 그리는 동작이 하나의 쓰레드에서 동시에 일어나게 된다.

 

우리가 Jsoup를 onCreate 에서 실행하게 되면, 웹크롤링 해오는 로딩시간에 앱이 정상적으로 UI를 그릴 수 없게 된다.

따라서 우리는 Thread를 하나 더 만들어주고, 그 쓰레드에서 웹크롤링을 수행할 것이다.

그러면 onCreate에서는 정상적으로 UI를 그리고 있고, 웹크롤링은 다른 쓰레드에서 처리하고 있기 때문에 정상 작동이 가능하다.

 

결론적으로, onCreate에서 하나의 쓰레드를 더 만들어서 웹크롤링을 수행할 것이고,

Handler를 사용해서 웹크롤링 쓰레드 -> 메인 쓰레드로 데이터를 주고받을 것이다.


이번 포스팅은 "1번. 날씨" 웹크롤링 부분에 대해서만 포스팅 할 것이다.

 

우선, 첫번쨰로 쓰레드를 하나 생성하자.

 

new Thread() {
            @Override
            public void run() {
                try {
                	//크롤링 할 구문
                } catch (IOException e) {
                    e.printStackTrace();
                }
         }
}.start();

 

이렇게 new Thread() 를 사용하여 쓰레드를 하나 생성해주고

run() 메소드를 오버라이딩 한 후 try-catch 구문을 사용하여 예외처리를 해준다.

그리고 try구문 안에 우리가 원하는 웹크롤링 코드를 짜면 되는것이다.

 

우선, 날씨를 크롤링 해올 것인데

나는 '서울 날씨' 에 대해서 크롤링 하고 싶다.

 

그래서 네이버에서 '서울 날씨' 를 검색했다.

 

이부분 이라고 표시한, 저 기온 부분과 맑음 부분을 끌어오려고 한다.

 

저 사이트에 들어가서 f12를 누른다.

그럼 개발자 모드가 뜰 것이다.

 

25도 부분을 선택해서 보면, strong으로 묶여있고, 상위 div의 클래스 네임이 "temperature_text" 이다.

참고로 클래스 네임은 .class , id 네임은 #id , 즉 . 과 # 로 구분한다.

 

그럼 이제 우리가 원하는 값의 클래스네임과 자료형을 알았으니까

웹크롤링을 시작해보자.

 

우선 전역변수로 URL 상수를 지정해주자.

private String URL = "https://m.search.naver.com/search.naver?sm=mtp_hty.top&where=m&query=%EC%84%9C%EC%9A%B8+%EB%82%A0%EC%94%A8";

그리고, 아까 만들었던 쓰레드의 try 구문 안에 웹크롤링 코드를 작성한다.

Document doc = Jsoup.connect(URL).get();	//URL 웹사이트에 있는 html 코드를 다 끌어오기
Elements temele = doc.select(".temperature_text");	//끌어온 html에서 클래스네임이 "temperature_text" 인 값만 선택해서 빼오기
isEmpty = temele.isEmpty(); //빼온 값 null체크
Log.d("Tag", "isNull? : " + isEmpty); //로그캣 출력
if(isEmpty == false) { //null값이 아니면 크롤링 실행
   tem = temele.get(0).text().substring(5); //크롤링 하면 "현재온도30'c" 이런식으로 뽑아와지기 때문에, 현재온도를 잘라내고 30'c만 뽑아내는 코드
   bundle.putString("temperature", tem); //bundle 이라는 자료형에 뽑아낸 결과값 담아서 main Thread로 보내기
}

주석을 자세하게 달아놔서 이해하기 편할 것 이다.

 

그럼 이제 메인 쓰레드에서의 처리를 해주자.

이 핸들러코드는 onCreate 밖에서 작성해주시면 됩니다.

 Handler handler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(@NonNull Message msg) {
                Bundle bundle = msg.getData();	//new Thread에서 작업한 결과물 받기
                textView.setText(bundle.getString("temperature"));	//받아온 데이터 textView에 출력
        };

Handler 를 이용해서 새로운 쓰레드에서 했던 작업의 결과물을 주고받고 할 것이다.

아까 위에서 bundle 이라는 자료형에 결과물을 담아서, key값을 "temperature" 로 정해준 후 담아서 보냈다.

 

그럼 이제 메인쓰레드에서는 그걸 받아서 textView에 뿌려주면 되는 것이다.

네이버 '대전날씨' 검색 후 크롤링 한 결과이다.

위에서 한 코드로는 "31'c" 까지 출력 가능한 것.

위에서 사용한 코드를 이용하여 계속 뽑아낼 수 있을 것이다.


그래서 제작 완료한 데일리 브리핑 어플

데일리 브리핑 어플

이런식으로, 현재 날짜와 시간을 표시 후에 간단한 인사말을 띄워준다.

인사말은 시간에 따라 동적으로 변한다.

그리고 밑에 준비된 버튼을 누르면 브리핑 화면으로 넘어간다.

 

사용자가 설정해둔 지역으로 크롤링 되며, 첫번째 칸에는 현재 날씨

두번째 칸에는 오늘 신규확진자수

세번째 칸에는 현재 주요 뉴스 헤드라인 을 보여준다.

 

모두 웹크롤링을 이용한 것이며, 위의 코드로 이루어져 있다.

다음엔 또 새로운 아이디어로 새로운 크롤링 어플을 만들어 봐야겠다.


급하게 써서 조금 뒤죽박죽인 감이 있지만

잘 모르는 부분이 있으면 댓글 달아주시면 답변 해드릴게요!

 

 

 

반응형
Comments