본문 바로가기
[업무 지식]/Crawling

[Selenium] CGV review Crawling

by 에디터 윤슬 2025. 1. 3.

라이브러리 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

 

동작 요약

  1. Selenium WebDriver로 지정된 URL을 엽니다.
  2. 각 페이지에서 작성자 이름, 리뷰 내용, 작성 날짜, 좋아요 수 데이터를 크롤링하여 리스트에 저장합니다.
  3. 모든 데이터를 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