셀레늄으로 이용할 수 있는게 많을 듯 하다 어여 공부하고 써먹어봐야지
영상에 나와있는 구글무비는 없고.... 뷰티풀수프로 스크래핑 자꾸 안되서 미치게뜸 . . . 하하
근데 어려운데 재밋다

나도코딩 님의 동영상 정리 (chapter 27~30. selenium 활용 ; 구글 무비)
https://www.youtube.com/watch?v=yQ20jZwDjTE
동적 페이지에 대한 웹스크래핑
일단 페이지가 접속될 때 바로 불러와지는 것이 아닌, 사용자가 동적을 했을 때 그때 동작하는 것
예: 스크롤 내렸을 때 새로운 목록 갱신
나도 코딩님 영상에서 '구글무비' 사이트에서 진행하라고 하셨는데, 안타깝게도 오래된 영상이라 그런지 ...
지금은 현재 불가능한 사이트였듬
따라서 비슷한 사이트를 가지고 진행해보로고 하겠음

! requests와 BeautifulSoup4를 가지고 영화 사이트에서 웹스크래핑 & selenium을 가지고 동일 사이트에서 웹스크래핑 !
Requests, BeautifulSoup4
1. 세팅 작업
requests, beautifulsoup작업
- 넷플릭스, 웨이브, 애플티비 등은 JavaScript로 동적 생성되어 html을 못가져온다고 한다 . . chat gpt말에 의하면
원하는 정보들 (영화정보)는 JS 실행 후에 생성됨 => bs4로 html 긁어도 데이터가 없어서 가지고 오지 못함 - 여러 사이트를 통해 시도해보았지만 가지고와지지 않았다 ... ㅠ
- 그래서 그나마 cine21을 통해서 되는 듯 하여 해보았으나 이것도 역시 ... 윗부분만 가져오고 원하는 영화명, 평점 등은 스크래핑 되지 않았음. ...
(div class를 다르게 해서 html 가지고와도 스크래핑 되는 html이 동일한 것을 보면 내가 갖고 오고 싶은 영화정보 쪽들은 막혀있는 듯 하다) - chat gpt 에 의하면 이런 경우, selenium을 사용해서 실제 브라우저 열고 JS 실행까지 기다린 다음 html을 가지고 오면 된다고 함
- 그러나 일단 시도했던 코드를 공유하고자 한다
import requests
from bs4 import BeautifulSoup
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
"Accept-Language":"ko-KR, ko"} # 만약 영어 사이트라 자동 번역되어 한글이 나오는 경우면, 웹스크래핑 할 때 영어로 스크랩. 따라서, 한글로 나오도록 설정
url = "https://cine21.com/movie/rank"
res = requests.get(url, headers=headers)
res.raise_for_status()
print(res.status_code)
soup = BeautifulSoup(res.text, "lxml")
2. 전체 영화정보 스크래핑하여 파일에 넣기 + 영화명만 출력
- headers에 User-Agents와 Accept-Language 내용 삽입 필요 + res = request.get(headers=headers)
영어 사이트가 자동 번역되어 한글로 출력되는 경우, 웹스크래핑에서 한글 나오지 않음. 따라서 한글로 스크래핑 하기 위해 ko-KR로 지정 필요 - 나머지는 requests, beautifulsoup4에서 꼭 사용되어지는 코드들 !
# 전체 문서 스크래핑
movies = soup.find_all("div", class_="list_with_upthum_item")
print(len(movies))
# 스크래핑 한 html을 movies.html에 저장
with open("movies.html", "w", encoding = "utf8") as f:
f.write(soup.prettify()) # prettify = html 문서를 예쁘게 출력
# 스크래핑 한 정보들 중, 영화명 (title) 부분만 출력
for movie in movies:
title = movie.find("p", class_="title").get_text()
print(title)
- 아래 사진을 보면 알겠지만, 모든 영화들은 div class="list_with_upthumb_item"으로 묶여있음
따라서, find_all 로 묶어서 진행 - with open을 통해 "movies.html"이라는 파일 생성하고, write 형식으로 생성, utf8 인코딩 조건으로 생성
- soup.prettify() : html 문서를 브라우저에서 보이는 그런 정갈한 html 순서로 예쁘게 출력시켜줌
- 원래 html 정보가 스크래핑 되었다면, 저장된 movies 내에서 각 movie 정보들을 꺼내서, p tag의 title이라는 클래스 데이터들을 title에 저장해서 print

Selenium
1. 세팅 작업
selenium 작업
- "페이지 이동" 까지는 이미 이전에 했기에 스킵 하겟슴 ~
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
options = Options()
options.add_argument("--start-maximized")
options.add_experimental_option("detach", True)
# 1. 페이지 이동
browser = webdriver.Chrome(options= options)
url = "https://cine21.com/movie/rank"
browser.get(url)
2. 스크롤 내리기
2-1. 지정한 위치로 스크롤 내리기
browser.execute_script("window.scrollTo(0, 1080)")
- 스크롤 내리기에서 0, 1080 은 내 컴퓨터 해상도 : 즉, (해상도) 모니터 높이인 1080 위치로 스크롤 내리기
- 컴퓨터 해상도 확인 방법 : 바탕화면 > 마우스 우클릭 > 디스플레이 설정 > 해상도 확인

2-2. 화면 가장 아래로 스크롤 내리기
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
반복 작업 진행
- whil 문을 통해 반복하다가, prev_height 와 curr_height 동일할 때, 끝냄
prev_height : 이전 문서 높이 / curr_height : 현재 문서 높이
스크롤 했는데, 이전 문서 높이와 현재 문서 높이가 동일 => 스크롤 할 게 없음 => while문 끝내기 - 순서
- 스크롤 가장 아래로 내림
- 페이지 로딩 대기
interval=2 를 따로 만들어서 time.sleep(interval)로 넣음 - '더보기'누르기
아래 이미지와 같이 내리다보면 '더보기'란이 있어서 눌러야만 내려감

# 2. 스크롤 내리기
# 2-1. 지정한 위치로 스크롤 내리기
browser.execute_script("window.scrollTo(0, 1080)") # 1920 X 1080
time.sleep(2)
# 2-2. 화면 가장 아래로 스크롤 내리기
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(2)
# '더보기' 누르기
browser.find_element(By.XPATH, '//*[@id="container"]/section[3]/div/div[2]/button').click()
interval = 2 # 2초에 한번씩 스크롤 내림
# 현재 문서 높이를 가져와서 저장
prev_height = browser.execute_script("return document.body.scrollHeight")
# 반복 수행
while True:
# 스크롤을 가장 아래로 내림
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
# 페이지 로딩 대기
time.sleep(interval)
# '더보기'누르기
browser.find_element(By.XPATH, '//*[@id="container"]/section[3]/div/div[2]/button').click()
# 현재 문서 높이를 가져와서 저장
curr_height = browser.execute_script("return document.body.scrollHeight")
if curr_height == prev_height: # 끝까지 내린 경우, 아무리 내려도 과거 문서 높이와 현재 문서 높이가 동일 => 스크롤 멈춤
break
print("스크롤 완료")
Selenium + requests와 bs4
selenium을 통해 스크롤해서 html 가지고 오고, 그것을 requests와 bs4를 통해 원하는 값 스크래핑하기 !
위 두 코드를 합쳐서 진행하는 것
그러나 중간 중간 코드 수정 및 삭제했으므로 그 부분은 찝어서 설명하겟으며, 전체 코드는 맨 아래에 기재해놓음
- 하기 내용 추가 : 알림 팝업 에러 방지
- selenium으로 browser.page_source 호출할 때, 브라우저에 알림 팝업 떠 있으면 에러 발생 => 맨 마지막 페이지 다가가면 알림 팝업 뜸
- 따라서, try-except 구조로 에러 처리
- "정상적으로 html 읽기 -> 에러 발생 시 alert 처리 후 다시 시도"
- 여기서 중요한 부분 !! soup = None
- 저렇게 정의하지 않으면, soup 이 defined 되지 않았다고 에러 뜸
- soup = None은 초기 설정, BeautifulSoup (...)이 진짜 데이터 넣는 단계
단지, soup이 존재하지만 아직 값이 없다는 상태로 남게 하여 defined 시켜주며, 에러 방지
- soup = BeautifulSoup(res.text, "lxml") -> soup = BeautifulSoup(browser.page_source, "lxml") 변경
from selenium.common.exceptions import UnexpectedAlertPresentException, NoAlertPresentException
from selenium.webdriver.common.alert import Alert
soup = None
try:
soup = BeautifulSoup(browser.page_source, "lxml") # 사이트에서 맨 아래까지 스크롤한 html 정보 수집할 예정
except UnexpectedAlertPresentException:
try:
alert = browser.switch_to.alert
print("알림창 내용:", alert.text)
alert.accept() # "확인" 클릭
soup = BeautifulSoup(browser.page_source, "lxml")
except NoAlertPresentException:
print("알림창이 이미 닫혀 있음")
soup = BeautifulSoup(browser.page_source, "lxml") # 그래도 한 번 더 시도
- while True 대신 while count < 11로 사용: 에러 발생 가능성 감소
- 맨 아래까지 계속 내리다보면 에러 뜸 + 알림 팝업창 으로 인한 에러 생성
- 에러 발생을 줄이기 위해, '더보기' 선택 지정
- while count < 11 : "11번 진행"
coutn += 1 : "돌때마다 1번씩 플러스"
# 반복 수행
count = 0
while count < 11:
# 스크롤을 가장 아래로 내림
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
# 페이지 로딩 대기
time.sleep(interval)
# '더보기'누르기
browser.find_element(By.XPATH, '//*[@id="container"]/section[3]/div/div[2]/button').click()
count += 1
print("스크롤 완료")
- requests, bs4에서 작성했던 아래 코드 삭제 : 이미 selenium 내용 겹치므로 삭제
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
"Accept-Language":"ko-KR, ko"} # 만약 영어 사이트라 자동 번역되어 한글이 나오는 경우면, 웹스크래핑 할 때 영어로 스크랩. 따라서, 한글로 나오도록 설정
url = "https://cine21.com/movie/rank"
res = requests.get(url, headers=headers)
res.raise_for_status()
print(res.status_code)
전체 코드는 아래와 같음
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
from selenium.common.exceptions import UnexpectedAlertPresentException, NoAlertPresentException
from selenium.webdriver.common.alert import Alert
options = Options()
options.add_argument("--start-maximized")
options.add_experimental_option("detach", True)
# 1. 페이지 이동
browser = webdriver.Chrome(options= options)
url = "https://cine21.com/movie/rank"
browser.get(url)
time.sleep(1)
# 2. 스크롤 내리기
# 2-1. 지정한 위치로 스크롤 내리기
browser.execute_script("window.scrollTo(0, 1080)") # 1920 X 1080
time.sleep(1)
# 2-2. 화면 가장 아래로 스크롤 내리기
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
time.sleep(1)
# '더보기' 누르기
browser.find_element(By.XPATH, '//*[@id="container"]/section[3]/div/div[2]/button').click()
interval = 1 # 1초에 한번씩 스크롤 내림
# 반복 수행
count = 0
while count < 11:
# 스크롤을 가장 아래로 내림
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
# 페이지 로딩 대기
time.sleep(interval)
# '더보기'누르기
browser.find_element(By.XPATH, '//*[@id="container"]/section[3]/div/div[2]/button').click()
count += 1
print("스크롤 완료")
import requests
from bs4 import BeautifulSoup
soup = None
try:
soup = BeautifulSoup(browser.page_source, "lxml") # 사이트에서 맨 아래까지 스크롤한 html 정보 수집할 예정
except UnexpectedAlertPresentException:
try:
alert = browser.switch_to.alert
print("알림창 내용:", alert.text)
alert.accept() # "확인" 클릭
soup = BeautifulSoup(browser.page_source, "lxml")
except NoAlertPresentException:
print("알림창이 이미 닫혀 있음")
soup = BeautifulSoup(browser.page_source, "lxml") # 그래도 한 번 더 시도
movies = soup.find_all("div", class_="list_with_upthumb_item")
print(len(movies))
for movie in movies:
title = movie.find("p", class_="title").get_text()
print(title)
굉장히 오래걸렸다만 ... 값은 나온듯


'공부 & 프로젝트 > 파이썬' 카테고리의 다른 글
| [파이썬] 웹크래핑 활용 3-2 : BeautifulSoup4 (0) | 2025.10.20 |
|---|---|
| [파이썬] 웹크래핑 기초 3-1 : BeautifulSoup4 기본 (0) | 2025.10.20 |
| [파이썬] 웹크래핑 기초 5-3: Selenium 활용 - 네이버 항공권 (0) | 2025.10.20 |
| [파이썬] 웹크래핑 기초 5-2: Selenium 심화 - 로그인 (0) | 2025.10.20 |
| [파이썬] 웹스크래핑 기초 5-1: selenium 기본 (0) | 2025.10.18 |