728x90
반응형
영화 데이터수집 웹크롤링
크롤링 Crawling
소프트웨어 따위가 웹을 돌아다니며 유용한 정보를 찾아 특정 데이터베이스로 수집해 오는 작업. 또는 그러한 기술
다음 영화 사이트 웹크롤링
- URL : http://movie.daum.net
- 다음영화 > 랭킹 > 박스오피스 > 월간 위치의 데이터 수집
- 수집데이터 : 영화제목, 평점, 댓글
- 생성할 데이터 : 긍정/부정 ( 별점 점수 별 긍정인지 부정인지 판단하는 데이터 생성 )
- 프로그램에서 https://movie.daum.net/ranking/boxoffice/monthly 주소를 열어서 크롬에서 제어
웹크롤링 라이브러리
- 정적인 웹크롤링을 할 경우
- BeautifulSoup : 하나의 페이지에 보이는 부분만 수집할 때 사용
- 동적인 웹크롤링을 할 경우
- selenium : 클릭과 같은 이벤트 등 페이지 전환을 하면서 수집할 때 사용
- 동적 웹페이지 처리를 위한 라이브러리
- Prompt에서 설치 필요 : pip install selenium
- from selenium import webdriver
- webdriver : 브라우저 자체를 컨트롤 함
- 웹페이지 내에 데이터 추출을 위한 라이브러리
- from selenium.webdriver.common.by import By
- By : 페이지 안에 있는 html을 컨트롤 함
- from selenium.webdriver.common.by import By
- 시간 라이브러리
- import time
- 웹브라우저에 접근 할 때 페이지에 클릭이라는 동적 이벤트를 발생시킨다. 이때 네트워크 사양에 따라 느리게 실행 될 수 있고 다른 pc보다 빠르게 실행 될 수 있다. 즉, 사양에 따라 페이지 로딩 시간이 다르게 나타난다다. 그 로딩시간에 다른 행동을 하지 못하도록 즉, 외부에서 읽어들일 수 있는 시간을 주기 위해 time 사용
1. 크롬 브라우저 띄우기
- 브라우저 컨트롤
driver = webdriver.Chrome()
- url을 이용하여 페이지 접근
- get() : 페이지에 접근 후 해당 html 코드 읽어 들이기
- driver 객체가 모든 정보를 가지고 있음
driver.get("https://movie.daum.net/ranking/boxoffice/monthly")
2. 제목이 있는 부분의 html 태그 경로(패스) 추출하기
- 크롬브라우저 → F12(개발자도구) → 영화제목 마우스 우클릭 → [검사] 클릭 → a 태그에 마우스 위치 후 우클릭 → copy → copy selector 클릭 → 해당 제목의 위치 저장

- 영화 제목이 있는 a 태그 위치 경로 확인
- li:nth-child(1)에서 :nth-child(1) 이걸 빼면 ol아래 모든 li가 해당 된다.
movie_path = "#mainContent > div > div.box_boxoffice > ol > li > div > div.thumb_cont > strong > a"
- 현재 크롬브라우저에 보이는 영화제목 모두 추출하기
- find_element() : 한건 조회
- find_elements() : 여러건 조회(리스트 타입으로 반환)
- By.CSS_SELECTOR : CSS 스타일 경로를 인식할 수 있도록 지정
movie_elements = driver.find_elements(By.CSS_SELECTOR, movie_path)
print(f"movie_elements length = {len(movie_elements)}")
# 리스트 타입 0번째 제목 , 태그와 태그 사이에 text가 들어있다.( .text로 접근 )
print(f"title[0] =>> {movie_elements[0].text}")
print(f"movie_elements(제목) = {movie_elements}")

- 웹크롤링 처리가 모두 완료되면, driver 종료해야 한다
driver.quit()
- try - except로 처리하기
try:
driver = webdriver.Chrome()
driver.get("https://movie.daum.net/ranking/boxoffice/monthly")
movie_path = "#mainContent > div > div.box_boxoffice > ol > li > div > div.thumb_cont > strong > a"
movie_elements = driver.find_elements(By.CSS_SELECTOR, movie_path)
print(f"movie_elements length = {len(movie_elements)}")
print(f"title[0] =>> {movie_elements[0].text}")
print(f"movie_elements(제목) = {movie_elements}")
except Exception as e:
print(e)
driver.quit()
finally:
driver.quit()
3. Click ( ) 이벤트 발생시키기 (1) - 상세 페이지
아래 코드는 모두 for i 문 안에 작성된 코드
- 제목을 클릭 시켜서 상세 페이지로 이동하기
- 마우스로 제목을 클릭하는 행위와 동일한 코드
- click() 이벤트 발생
# 제목 10개만 추출하기
for i in range(10) :
title = movie_elements[i].text.strip()
print(f"No[{i}] / title[{title}] Start----------------")
### 제목을 클릭 시켜서 상세 페이지로 이동하기
movie_elements[i].click()
- 상세페이지로 접근했다라는 정보를 받아오기
- 실제 상세페이지에 접근
- window_handles : 페이지가 열릴때 마다 리스트타입으로 윈도우 정보를 순서대로 가지고 있는 객체이다. -1 은 마지막에 접근한 페이지를 의미한다.
movie_handle = driver.window_handles[-1]
# - 새로 열린 페이지로 전환하기
driver.switch_to.window(movie_handle)
- 페이지 로딩 및 코드 읽어들이는 시간을 벌어주기
time.sleep(1)
→ 여기까지 실행하면 웹 페이지 열리고 영화 '서울의 봄' 상세페이지까지 들어갔다가 종료됨
4. Click ( ) 이벤트 발생시키기 (2) - [평점]
- [평점] 탭 클릭 이벤트 발생 시키기

tap_score_path = "#mainContent > div > div.box_detailinfo > div.tabmenu_wrap > ul > li:nth-child(4) > a"
- a태그 정보 가지고 오기
tap_score_element = driver.find_element(By.CSS_SELECTOR, tap_score_path)
- [평점] 탭, 즉 a태그 클릭 이벤트 발생시키기[평점] 페이지로 접근했다라는 정보를 받아오기
tap_score_handle = driver.window_handles[-1]
# - 새로 열린 페이지로 전환하기
driver.switch_to.window(tap_score_handle)
- 페이지 로딩 및 코드 읽어들이는 시간을 벌어주기
time.sleep(1)
5. 모든 평점 / 리뷰 데이터 추출하기
- 모든 평점 데이터 추출하기
score_path = "ul.list_comment div.ratings"
score_lists = driver.find_elements(By.CSS_SELECTOR, score_path)
print(f"평점 갯수 : {len(score_lists)}")
- 모든 리뷰 데이터 추출하기
comment_path = "ul.list_comment p.desc_txt"
comment_lists = driver.find_elements(By.CSS_SELECTOR, comment_path)
print(f"리뷰 갯수 : {len(comment_lists)}")

6. 평점을 이용하여 긍정 / 부정 값 생성하기
- 평점 또는 리뷰 데이터가 없을 수 있기에 두개 리스트의 갯수 중 작은 값을 사용
- 평점 또는 리뷰가 없으면, 수집에서 제외
- 기존의 for j in range(len(score_lists))으로 for문을 돌릴 때, 리뷰가 없을 경우 len(comment_lists)는 len(score_lists)와 길이가 다르기 때문에 오류가 난다.
for_cnt = 0
if len(score_lists) < len(comment_lists) :
for_cnt = len(score_lists)
elif len(score_lists) > len(comment_lists) :
for_cnt = len(comment_lists)
else :
for_cnt = len(score_lists)
아래 코드는 모두 for j 문 안에 작성된 코드
- 평점, 리뷰 추출하기
for j in range(for_cnt) :
### 평점 추출하기
score = score_lists[j].text.strip()
### 리뷰 추출하기
comment = comment_lists[j].text.strip().replace("\n", "")
print(f"{title} \t{score} \t{comment} \n")

- 평점을 이용해서 긍정/ 부정 데이터 생성
- 긍정 : 평점이 8이상인 경우로, 긍정값은 1 사용
- 부정 : 평점이 4이하인 경우로, 부정값은 0 사용
- 기타 : 나머지, 기타값은 2 사용
label = 0
if int(score) >= 8 :
label = 1
elif int(score) <= 4 :
label = 0
else :
label = 2
print(f"{title} \t{score} \t{comment} \t{label} \n")

7. 다시 메인으로 이동
아래 코드는 for j 문 밖에 작성된 코드
- 영화 한편에 대한 정보수집이 끝나면 다시 메인으로 이동
- execute_script() : 자바스크립트 문법 처리 함수
driver.execute_script("window.history.go(-2)")
time.sleep(1)
→ 여기까지 실행하면 영화 10개의 제목, 평점, 리뷰, 긍정/부정 데이터가 출력된다
8. 수집 데이터 저장하기
- 수집데이터 txt 파일로 저장시키기 ( 아래 코드는 for i 문 위에 작성된 코드)
f = open("./data/movie_reviews.txt", "w", encoding="UTF-8")
- 파일에 쓰기 ( 아래 코드는 for j문 에 작성된 코드)
f.write(f"{title}\t{score}\t{comment}\t{label}\n")
- 파일 자원 닫기 (아래 코드는 except 문에 작성된 코드)
f.close()

9. 모두 펼치기(더보기) 수행한 뒤 데이터 추출
아래 코드는 for i 문 안에서 모든 평점 데이터 추출하기 전에 작성된 코드
- [평점] 더보기 버튼 클릭하여 모든 평점 보이게 펼치기
- 처음에 실행했다가 오류난 이유는 영화의 평점 중에 리뷰가 적히지 않은게 있었음. 6번으로 가서 if 문 추가.
### - 펼친 갯수 확인 변수
more_view_cnt = 0
### 모두 펼치기(더보기) 수행
while True :
try:
more_view_path = "#alex-area > div > div > div > div.cmt_box > div.alex_more > button"
more_view_element = driver.find_element(By.CSS_SELECTOR, more_view_path)
more_view_element.click()
### 상세페이지로 접근했다라는 정보를 받아오기
movie_handle = driver.window_handles[-1]
# - 새로 열린 페이지로 전환하기
driver.switch_to.window(movie_handle)
### 페이지 로딩 및 코드 읽어들이는 시간을 벌어주기
time.sleep(1)
### 임시로 2번만 반복 처리 후 break 처리
# if more_view_cnt == 2 :
# break
### 더보기 클릭 횟수 확인을 위해 1씩 증
more_view_cnt += 1
except Exception as e :
### 더이상 더보기 버튼이 보이지 않으면 오류 발생
# - 오류 발생 시점이 더보기 버튼이 끝나는 시점
break
### 더보기 클릭획수 확인하기
print(f"더보기 클릭 횟수 : [{more_view_cnt}]")
→ 여기까지 실행하면 영화 10개의 제목과 더보기를 눌러 모두 펼쳤을 때의 평점, 리뷰, 긍정/부정 데이터가 출력된다
728x90
반응형
'Digital Boot > Database' 카테고리의 다른 글
[데이터 수집][Crawling] 영화 데이터 전처리 및 시각화 (2) (0) | 2023.12.05 |
---|---|
[데이터 수집][Crawling] 영화 데이터 전처리 및 시각화 (1) (4) | 2023.12.04 |
[Data Wrangling] 데이터 전처리 시각화 - 히트맵 / 막대그래프 / histplot / 선그래프 (1) | 2023.11.30 |
[Data Wrangling] 데이터 처리 시각화 (2) (0) | 2023.11.30 |
[Data Wrangling] 데이터 처리 시각화 (1) (1) | 2023.11.29 |