파이썬/파이썬 활용

파이썬 활용 08 - 4 - 웹 스크래핑 (Selenium - 구글 무비)

H-V 2021. 11. 8. 17:30

유투버 '나도코딩'님 강의 참조

 

 

* 동적 웹페이지 스크래핑을 해볼 예정

 

 

01 구글 무비 훑어 보기

동적인 웹페이지다. 사용자가 어떻게 사용하느냐에 따라 웹 페이지가 달라 진다.

 

  • 할인 중인 영화를 스크래핑 해보자
  1. 기본 세팅
    import requests
    from bs4 import BeautifulSoup
    
    url = "https://play.google.com/store/movies/top"
    res = requests.get(url)
    res.raise_for_status()
    soup = BeautifulSoup(res.text, "lxml")​
    기본적인 내용을 긁기 위해 BeautifulSoup을 이용

  2. 영화 검사
    각각의 <div> 태그들이 영화를 뜻하는 듯 하다.
  3. 1차 코드 시도
    movies = soup.find_all("div", attrs={"class":"ImZGtf mpg5gc"})
    print(len(movies))
    
    0​
    결과 값이 0으로 나온다 파일로 저장해서 이유를 한번 보자

  4. 파일로 저장하여 보기
    with open("movie.html", "w", encoding="utf8") as f:
        f.write(soup.prettify())​
  5. 저장된 파일을 웹브라우저로 열어보면 우리가 보고 있는 화면과 다르다. 그 이유는 구글에서 접속하는 사용자의 User Agent에 따라 다른 페이지를 주기 때문이다. 한글로 받기위해서 User Agent를 손봐야 한다.
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36",
        "Accept-Language":"ko-KR,ko"
    }​
  6. 이후 1차코드를 다시 해보면 결과값이 10개가 찍힌다. 10개만 찍히는 이유는 '구글 무비' 페이지 자체가 동적으로 변하기 때문이다
    BeautifulSoup에서는 이렇게 10개밖에 못가져오지만 Selenium에서는 동적으로 스크래핑이 가능하다


  7. 타이틀 가져오기 테스트


  8. import requests from bs4 import BeautifulSoup url = "https://play.google.com/store/movies/top" headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36", "Accept-Language":"ko-KR,ko" } res = requests.get(url, headers=headers) res.raise_for_status() soup = BeautifulSoup(res.text, "lxml") movies = soup.find_all("div", attrs={"class":"ImZGtf mpg5gc"}) print(len(movies)) # with open("movie.html", "w", encoding="utf8") as f: # f.write(soup.prettify()) for movie in movies: title = movie.find("div",attrs={"class":"WsMG1c nnK0zc"}).get_text() print(title) 베놈 Venom Free Guy 블랙 위도우 모가디슈 올드 분노의 질주: 더 얼티메이트 정글 크루즈 날씨의 아이 (자막) 더 수어사이드 스쿼드 보스 베이비 2

 

02 Selenium 사용하여 '구글 무비' 스크래핑

  • 구글 무비는 동적 웹페이지 + 스크롤을 내리면서 변하는 형태이다. 이 스크롤을 어떻게 하는지를 잘 배우자
  1. 기본 세팅
    from selenium import webdriver
    browser = webdriver.Chrome()
    browser.maximize_window()
    
    #페이지 이동
    url = "https://play.google.com/store/movies/top"
    browser.get(url)​


  2. 스크롤 처리
    #스크롤 내리기
    #자기 모니터 해상도에 따라 값이 다름
    browser.execute_script("window.scrollTo(0, 1080)")​
    스크롤이 잘 내려 간다
  3. 스크롤 한번이 아닌 끝까지 내리는 처리
    import time
    interval = 2
    
    ....
    
    #현재 문서 높이를 가져와서 저장
    prev_height = browser.execute_script("return document.body.scrollHeight")
    
    #반복 수행
    while True:
        browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
        time.sleep(interval) #로딩이 더 걸리면 interval을 늘리면 됨
    
        curr_height = browser.execute_script("return document.body.scrollHeight")
    
        if curr_height == prev_height:
            break
    
        prev_height = curr_height
    
    print("스크롤 완료")​
    1) prev_height = 0 → 스크롤 내림
    2) curr_height = 스크롤 내린 값 → prev_height ≠ curr_height 비교
    3) 같으면 멈춤 (결국 맨 밑에서 멈춤)
    4) 값이 다르면 prev_height 값이 현재 스크롤 내린값으로 변경

  4. 스크롤 처리가 됬으니 스크래핑 진행
    현재 스크래핑을 해보면 10개만 들고오는 현상이 있는데 이는 '구글 무비' 사이트가 스크롤링 이후 페이지가 바뀌기 때문이다. 그래서 확인을 해보면 10개 이후 페이지가 동적으로 변할때 여러태그들이 다시 나오는걸 볼 수있다.


  5. 다시 검사 진행
    스크롤 이후 새롭게 나오는 영화들은 <div> 태그로 전체가 감싸져서 나오는것을 볼 수 있다. 이를 이용 하자
  6. 코드로 접근
    from selenium import webdriver
    import time
    from bs4 import BeautifulSoup
    
    ...
    
    
    
    #반복 수행
    while True:
    	...
        
    soup = BeautifulSoup(browser.page_source, "lxml")
    
    movies = soup.find_all("div", attrs={"class":"Vpfmgd"})
    print(len(movies))
    
    for movie in movies:
        title = movie.find("div",attrs={"class":"WsMG1c nnK0zc"}).get_text()
        print(title)​

    굿
  7. 할인된 영화만 들고 오기
    원가격과 할인된 가격이 한 <div> 클래스에서 움직이는걸 볼 수 있다


  8. 코드로 접근
    soup = BeautifulSoup(browser.page_source, "lxml")
    
    movies = soup.find_all("div", attrs={"class":"Vpfmgd"})
    print(len(movies))
    
    for movie in movies:
        title = movie.find("div",attrs={"class":"WsMG1c nnK0zc"}).get_text()
        # print(title)
    
        # 할인 전
        original_price = movie.find("span", attrs={"class":"SUZt4c djCuy"})
        if original_price:
            original_price = original_price.get_text()
        else:
            # print(title, "<할인 되지 않은 영화>")
            continue
        
        # 할인 된 가격
        price = movie.find("span", attrs={"class":"VfPpfd ZdBevf i5DZme"}).get_text()
    
        # 링크
        link = movie.find("a", attrs={"class":"JC71ub"})["href"]
    
        print(f"제목:{title}")
        print(f"할인 전 가격:{original_price}")
        print(f"할인 후 가격:{price}")
        print("링크:","https://play.google.com"+link)
        print("-"*100)
    
    browser.quit()