들어가며
- 전 시간에 API 호출을 이요하여 원하는 데이터를 수집 하여 보았다.
- 하지만 모든 사이트에서 데이터를 호출하는 API 를 제공 하는 것은 아니다.
- 이런 경우에 사용할 수 있는 방법에 웹의 HTML 에 있는 데이터를 직접 가지고 오는 방법이다.
크롤링 하고자 하는 웹페이지의 개발자 모드 열기
- 우선 당연한 이야기지만 크롤링 하고자 하는 웹 페이지를 열어야 한다.
- 이번 시간에는 저번시간에 진행 했던 영화 정보를 크롤링을 통해 가져 오는것을 진행 해 보겠다.
- 우측의 연한 파란 부분이 좌측 웹 사이트의 영화 정보부분임을 알 수 있다.
- 또한 내부의 "inner_cont" 가 영화 정보를 답고 있음을 알 수 있다.
파일 생성
- 우선 크롤링코드를 적을 파일을 생성 해 준다.
jsoup의 간단한 사용법 (val html = Jsoup.connect(url).get() )일때
- select -
1. <div class="test"/> 처럼 class 이름이 test 일때
- val item = html.select("div.test")
2. <div id="test"/> 처럼 id 이름이 test 일때
- val item = html.select("div#test")
3. <div class="test"/> 내부의 a 태그만 가져 올때
- val item = html.select("div.test a")
- attr -
4. HTML 의 속성값을 가져 올때
ex) <a id="ID" href="test_href01" title="title01"> abcdefg </a>
- val item = html.select("a#ID")
- val attr = item.attr("href") // => test_href01
- text() -
5. 내부의 텍스트 값을 가져 오고 싶을 때(위의 예시에서 abcdefg 를 가져 올 때
- item.text() // => abcdefg
실제로 Jsoup 을 이용하여 크롤링 테스트
- 우선 보이는 대로 "inner_cont" class 를 그대로 크롤링 해 본다.
- 이젠 "Controller" 와 "Interface" 는 생략 한다.
//movieInfoServiceImpl.kt
package com.example.runjob_blog.Service.impl
import com.example.runjob_blog.Service.movieInfoService
import org.jsoup.Jsoup
import org.springframework.stereotype.Service
@Service
class movieInfoServiceImpl:movieInfoService {
override fun saveTimeTable(movieID: String){
val url = "https://movie.daum.net/moviedb/main?movieId=${movieID}"
val conn = Jsoup.connect(url)
val html = conn.get()
val inner_cont = html.select("div.inner_cont")
println(inner_cont)
}
}
- 여기서 주의 할 점은 class 이름이 "inner_cont" 인 div 가 여려개라면 모두 나온다는 것이다.
실제로 원하는 데이터만 크롤링
- 여기서 원하는 데이터는 위 데이터 내부의 <dl/> 부분이다.
- 다음과 같이 코드를 수정하면 <dl/> 부분만 가져 올 수 있다.
- 또한 <dl/> 처럼 개수가 많으면 배열처럼 사용 할 수 있다.
- 다음 이미지를 보면 inner_cont[0] 을 하면 가장 처음 dl 이 출력 되는것을 알 수 있다.
package com.example.runjob_blog.Service.impl
import com.example.runjob_blog.Service.movieInfoService
import org.jsoup.Jsoup
import org.springframework.stereotype.Service
@Service
class movieInfoServiceImpl:movieInfoService {
override fun saveTimeTable(movieID: String){
val url = "https://movie.daum.net/moviedb/main?movieId=${movieID}"
val conn = Jsoup.connect(url)
val html = conn.get()
val inner_cont = html.select("div.inner_cont dl")
println(inner_cont[0])
}
}
데이터 를 Hashmap 으로 정제
- 위 그림처럼 text 를 쭉 받아서는 사용 할 수 없다.
- 따라서 우리가 사용하기 편하게 "개봉 = 2023.03.08" 처럼 되어 있는것이 좋다.
- 먼저 데이터를 분석 해 보면 <dt> 태그 안에는 데이터의 이름이, <dd> 태그 안에는 데이터의 값이 들어 있다.
- 이를 토대로 inner_cont 를 반복돌려 hashmap 에 저장 한다.
- 필요에 따라 같은 방식으로 이름도 데이터에 추가하면 다음과같이 된다.
package com.example.runjob_blog.Service.impl
import com.example.runjob_blog.Service.movieInfoService
import org.jsoup.Jsoup
import org.springframework.stereotype.Service
@Service
class movieInfoServiceImpl:movieInfoService {
override fun saveTimeTable(movieID: String){
val movieInfo = HashMap<String, String>()
val url = "https://movie.daum.net/moviedb/main?movieId=${movieID}"
val conn = Jsoup.connect(url)
val html = conn.get()
val inner_cont = html.select("div.inner_cont dl")
val movieTit = html.select("span.txt_tit")[0].text()
movieInfo["이름"] = movieTit
for(oneCont in inner_cont){
val contName = oneCont.select("dt").text()
val contVal = oneCont.select("dd").text()
movieInfo[contName] = contVal
}
println(movieInfo)
}
}
'Runjob(런잡 프로젝트) > SpringBoot + Kotlin' 카테고리의 다른 글
[SpringBoot + Kotlin] Scheduled DB 의 업데이트 날짜와 비교해서 실행 (0) | 2023.04.24 |
---|---|
[SpringBoot + Kotlin] @scheduled로 스케줄 처리 및 corn 설정 (0) | 2023.04.24 |
[SpringBoot + Kotlin] Jsoup을 이용하여 프로그램에서 API 호출 (0) | 2023.04.22 |
[SpringBoot + Kotlin] JPA Repositor를 이용해 DB 에 원하는 데이터 저장 (0) | 2023.04.19 |
[SpringBoot + Kotlin] Controller 를 통해 request 보내기(실행하기) (0) | 2023.04.19 |