라이브러리 import
#pip install selenium
# 크롬브라우저 업데이트 될 때마다 driver 재설치를 하지 않기 위해 설치
#pip install webdriver-manager
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
import time
import pandas as pd
import warnings # 경고창 무시
warnings.filterwarnings('ignore')
review crawling 함수 생성
def get_movie_reviews(url, page_num=12):
# ChromeDriver 경로 설정
chrome_driver_path = '/Users/t2023-m0089/python/chromedriver-mac-arm64/chromedriver'
service = ChromeService(chrome_driver_path)
# WebDriver 초기화
options = webdriver.ChromeOptions()
wd = webdriver.Chrome(service=service, options=options)
# 빈 리스트 생성하기
writer_list = []
review_list = []
date_list = []
like_list = []
try:
wd.get(url)
wait = WebDriverWait(wd, 10) # 명시적 대기 설정 (최대 10초)
for page_no in range(1, page_num + 1): # 1페이지에서 page_num까지의 리뷰 추출
try:
# 페이지 이동 버튼 클릭
page_ul = wait.until(EC.presence_of_element_located((By.ID, 'paging_point')))
page_a = page_ul.find_element(By.LINK_TEXT, str(page_no))
page_a.click()
# 각 페이지의 데이터를 추출
writers = wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'writer-name')))
writer_list += [writer.text for writer in writers]
reviews = wd.find_elements(By.CLASS_NAME, 'box-comment')
review_list += [review.text for review in reviews]
dates = wd.find_elements(By.CLASS_NAME, 'day')
date_list += [date.text for date in dates]
likes = wd.find_elements(By.ID, 'idLikeValue')
like_list += [like.text for like in likes]
# 10페이지마다 다음 버튼 클릭
if page_no % 10 == 0:
next_button = wait.until(
EC.element_to_be_clickable((By.CLASS_NAME, "paging-side"))
)
next_button.click()
except Exception as e:
print(f"Error on page {page_no}: {e}")
break
finally:
wd.quit()
# Pandas DataFrame 생성
movie_review_df = pd.DataFrame({
"Writer": writer_list,
"Review": review_list,
"Date": date_list,
"Like": like_list
})
return movie_review_df
- 함수 정의 및 기본 설정
def get_movie_reviews(url, page_num=12):
•`url`: 리뷰를 크롤링할 웹 페이지의 URL입니다.
•`page_num`: 크롤링할 페이지 수로 기본값은 12입니다. 사용자가 값을 지정하지 않으면 12페이지까지 데이터를 가져옵니다.
- ChromeDriver 경로 설정
chrome_driver_path = '~~~~chromedriver'
service = ChromeService(chrome_driver_path)
•`chrome_driver_path`: ChromeDriver 실행 파일의 경로를 지정합니다. 이 경로는 사용자 시스템에 설치된 ChromeDriver의 위치와 일치해야 합니다.
•`ChromeService(chrome_driver_path)`: Selenium 4.x에서 ChromeDriver를 초기화하는 새로운 방식입니다. 드라이버 경로를 `ChromeService` 객체로 전달합니다.
- WebDriver 초기화
options = webdriver.ChromeOptions()
wd = webdriver.Chrome(service=service, options=options)
•`webdriver.ChromeOptions()`: Chrome 브라우저의 옵션을 설정하기 위한 객체입니다. 예를 들어, 헤드리스 모드(브라우저 창 없이 실행) 등 다양한 옵션을 추가할 수 있습니다.
•`webdriver.Chrome(service=service, options=options)`: Selenium WebDriver 객체를 생성합니다. 이 객체를 통해 브라우저를 제어하며, `service`와 `options`를 전달하여 초기화합니다.
- 빈 리스트 생성
writer_list = []
review_list = []
date_list = []
like_list = []
•각 리스트는 데이터를 저장하기 위해 생성됩니다:
•`writer_list`: 리뷰 작성자의 이름을 저장합니다.
•`review_list`: 리뷰 내용을 저장합니다.
•`date_list`: 리뷰 작성 날짜를 저장합니다.
•`like_list`: 좋아요 수를 저장합니다.
- 웹 페이지 열기 및 명시적 대기 설정
wd.get(url)
wait = WebDriverWait(wd, 10) # 명시적 대기 설정 (최대 10초)
•`wd.get(url)`: WebDriver가 지정된 URL을 엽니다.
•명시적 대기 (`WebDriverWait`):
•Selenium이 특정 조건(예: 요소가 로드됨)을 만족할 때까지 최대 10초 동안 대기합니다.
•이는 페이지 로딩 지연이나 동적 콘텐츠 로드 문제를 해결하기 위해 사용됩니다.
- 페이지 순회 및 데이터 추출
# 반복문으로 페이지 순회
for page_no in range(1, page_num + 1):
•페이지 번호를 `1부터 page_num까지` 반복하며 각 페이지에서 데이터를 추출합니다.
# 페이지 이동 버튼 클릭
page_ul = wait.until(EC.presence_of_element_located((By.ID, 'paging_point')))
page_a = page_ul.find_element(By.LINK_TEXT, str(page_no))
page_a.click()
•페이지 이동 버튼 찾기 (`paging_point`):
•HTML에서 ID가 `paging_point`인 요소(페이지 네비게이션 영역)를 찾습니다.
•특정 페이지 번호 버튼 클릭:
•`find_element(By.LINK_TEXT, str(page_no))`: 현재 순회 중인 `page_no`에 해당하는 링크 텍스트를 클릭하여 해당 페이지로 이동합니다.
# 데이터 추출
# 작성자 이름 추출
writers = wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'writer-name')))
writer_list += [writer.text for writer in writers]
•HTML 클래스 이름이 `writer-name`인 모든 요소를 찾습니다.
•각 작성자의 이름(`writer.text`)을 리스트에 추가합니다.
# 리뷰 내용 추출
reviews = wd.find_elements(By.CLASS_NAME, 'box-comment')
review_list += [review.text for review in reviews]
•HTML 클래스 이름이 `box-comment`인 모든 요소에서 리뷰 내용을 추출하여 리스트에 추가합니다.
# 작성 날짜 추출
dates = wd.find_elements(By.CLASS_NAME, 'day')
date_list += [date.text for date in dates]
•HTML 클래스 이름이 `day`인 모든 요소에서 작성 날짜를 추출하여 리스트에 추가합니다.
# 좋아요 수 추출
likes = wd.find_elements(By.ID, 'idLikeValue')
like_list += [like.text for like in likes]
•HTML ID가 `idLikeValue`인 요소에서 좋아요 수를 추출하여 리스트에 추가합니다.
- 다음 페이지로 이동(10페이지마다)
if page_no % 10 == 0:
next_button = wait.until(
EC.element_to_be_clickable((By.CLASS_NAME, "paging-side"))
)
next_button.click()
•페이지 번호가 `10의 배수일 때`, “다음” 버튼(`paging-side`)을 클릭하여 다음 페이지 그룹으로 이동합니다.
- 예외 처리
except Exception as e:
print(f"Error on page {page_no}: {e}")
break
•각 페이지에서 오류가 발생하면 예외 메시지를 출력하고 반복문을 종료합니다.
- Webdriver 종료
finally:
wd.quit()
•WebDriver 세션을 종료하여 브라우저 창을 닫고 리소스를 해제합니다.
- 데이터프레임 생성 및 반환
movie_review_df = pd.DataFrame({
"Writer": writer_list,
"Review": review_list,
"Date": date_list,
"Like": like_list
})
return movie_review_df
동작 요약
- Selenium WebDriver로 지정된 URL을 엽니다.
- 각 페이지에서 작성자 이름, 리뷰 내용, 작성 날짜, 좋아요 수 데이터를 크롤링하여 리스트에 저장합니다.
- 모든 데이터를 Pandas DataFrame으로 변환한 뒤 반환합니다.
영화(뽀로로) 댓글 데이터 추출
# url 과 pagenum 을 입력하여 작성자, 리뷰내용, 작성날짜, 좋아요 수 요청 및 dataframe 반환
movie_review_df = get_movie_reviews("http://www.cgv.co.kr/movies/detail-view/?midx=89099", page_num=12)
movie_review_df
'[업무 지식] > Crawling' 카테고리의 다른 글
[서울시 열린데이터] 서울시 상권분석서비스(소득소비-상권) (0) | 2025.01.03 |
---|---|
[NAVER API] 쇼핑인사이트 (0) | 2025.01.03 |
[ETL] Weather, MySQL 클래스를 객체화 (0) | 2025.01.02 |
[geocode] GeoJSON의 내용을 출력하는 HTML (0) | 2025.01.02 |
[geocode] 지오코딩으로 위치 정보 추출하기 (0) | 2025.01.02 |