Software Engineering/Android

[Android][Kotlin] jsoup로 HTML 파싱하기

iseop 2021. 12. 10. 20:23   인쇄용 버전

요즘 그냥 재미로 안드로이드 앱을 만들고 있습니다. 학습 자료는 https://developer.android.com/courses/android-basics-kotlin/course 에서 제공하는 강의를 따라가는 중입니다. Android Studio에서 Kotlin을 사용해 진행됩니다.

친구가 로또 번호가 동행복권 홈페이지에 올라오면 입력했던 번호와 대조해서 결과를 notification으로 알려주는 앱을 만들어 보라 했는데, 일단 그 번호를 가져오는 방법을 정리해 두었습니다.

 

그래서 안드로이드 service와 notification 사용 방법을 알아야겠구나! 했는데, WorkManager라는 새로운 방식으로 만들어야 한다고 합니다.

 

추가로, 네트워크에서 웹페이지를 받아올 때 AsyncTask 대신에 다른 방법을 찾아봐야 할 것 같습니다. AsyncTask를 만들면 Android Studio에서 검은색 취소선을 그어줍니다. 찾아봤더니 deprecate된 요소를 그렇게 표시해 준다고 합니다. AsyncTask는 2019년 11월에 deprecate 되었습니다.

 

제일 먼저 할 일은 AndroidManifest.xml 속 <application> 태그 바로 위에 아래 내용을 추가하는 것입니다.

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

 

다음으로 https://jsoup.org/download에서 core library를 다운로드해서 프로젝트의 app/libs 디렉터리에 저장하고, Android Studio로 돌아와서 Add As Library 메뉴를 눌러 추가했습니다. 프로젝트 보기 방식이 기본 Android로 되어 있는데, 저는 Project 보기로 바꿨습니다.

그리고 가장 최근 회차와 당첨번호를 포함한 String을 반환하는 fetchLastResult() 함수를 작성했습니다. 물론 안드로이드 스튜디오는 AsyncTask와 관련 메소드에 취소선을 쭉 그어줬습니다.

JsoupAsyncTask라는 private class를 만들고, Ctrl+O를 눌러 doInBackground 메소드를 찾고 OK, 그리고 실행할 코드를 작성했습니다. 그렇게 해서 받아온 HTML Document를 file 변수에 저장하고 select() 메소드에 CSS 쿼리를 넣어 원하는 값을 추출했습니다.

 

private fun fetchLastResult(url: String): String {
    val task = JsoupAsyncTask(url)
    task.execute(url)

    val file: Document = task.get()
    val dateQuery = "div.win_result p.desc"
    val ordinalNumQuery = "div.win_result h4 strong"

    val date = file.select(dateQuery).text().toString()
    val ordinalNum = file.select(ordinalNumQuery).text().toString()

    return if (url.contains("win720")) {
        val balls = file.select("div.win_num_wrap span.num.large span").text().toString()
        "연금복권 $ordinalNum: ${balls.take(14)}\n" +
        "*보너스: ${balls.takeLast(12)}\n$date"
    } else {
        val balls: String = file.select("span.ball_645").text().toString()
        "로또6/45 $ordinalNum: $balls\n" +
        "$date\n\n"
    }
}

private class JsoupAsyncTask(val url: String) : AsyncTask<Any, Int, Document>() {
    override fun doInBackground(vararg p0: Any?): Document {
        return Jsoup.connect(url).get()
    }
}

 

실행 결과