셀레니움을 이용한 넷플릭스 스크래핑 [project]

hyeok2·2023년 6월 22일

python

목록 보기
2/7
post-thumbnail

영화추천시스템을 위한 db구축

영화추천시스템에서 필요한 것

  • 부트캠프에서 진행중인 final project의 주제를 영화 추천 시스템으로 선정했다.
  • 추천시스템에서 가장 중요한건 양질의 데이터이다.
    -> 디즈니플러스, 티빙등의 OTT와 영화관 3사의 웹 스크래핑(크롤링)과 TMDB의 api를 이용하기로 하였다.

OTT 웹 스크래핑

1. 먼저 넷플릭스의 현재 상영중인 시리즈(TV)의 데이터와 영화 데이터는 셀레니움을 이용한 웹 스크래핑을 생각하게 되었다.

2. 작품 제목, 썸네일, 세부정보url 가져오기

  • 넷플릭스의 시리즈 내림차순 주소를 접속
  • send_keys를 이용하여 page_down을 반복
  • xpath를 find_element로 이름, 상세정보 url, 썸네일을 찾은 후 각각의 리스트에 append.
def get_prevalue(driver): #이름, 세부정보 url, 이미지url 가져오기
    #시리즈주소 입력
    driver.get(serise_url_up)
    #리스트 생성
    S_name=[]
    S_url=[]
    S_img=[]
    #pgdown 반복
    for i in range(0, 400, 1): #page_down 할 횟수
        driver.find_element(by='tag name', value='body').send_keys(Keys.PAGE_DOWN) # 페이지다운 반복
        time.sleep(0.1)
        
    slider_items = driver.find_elements(by='xpath',value='//div[starts-with(@class, "slider-item")]')

    for item in slider_items:
        tag = item.find_element(by='xpath', value='.//a')
        name = anchor_tag.get_attribute('aria-label')
        url = anchor_tag.get_attribute('href')
        image_url = item.find_element(by='xpath', value='.//img').get_attribute('src')

        S_name.append(name)
        S_url.append(url)
        S_img.append(image_url)
        
    S_detail = [url.split('?')[0].replace("/watch/", "/browse/genre/83?so=az&jbv=") for url in S_url]    
    return S_name, S_url, S_img, S_detail

3. 가져온 세부정보 url을 이용하여 세부정보 가져오기

def get_detailvalue(driver, S_name, S_detail):  #세부정보 가져오기 크리에이터, 출연, 장르, 시리즈특징, 관람등급, 방송사, 상영일자
    S_creator = []  # 크리에이터
    S_actor = []  # 출연
    S_genre = []  # 장르
    S_char = []  # 시리즈 특징
    S_age = []  # 관람 등급
    S_BC = []  # 방송사
    S_year = []  # 상영일자

    for detail_url in S_detail:
        driver.get(detail_url)

        # 클래스 요소 찾기
        tags = driver.find_elements(by='class name', value='previewModal--tags')

        # 기본값 설정
        creator = None
        actor = None
        genre = None
        char = None
        BC = None
        age = None
        year = None

        for tag in tags:
            label = tag.find_element(by='class name', value='previewModal--tags-label').text
            items = tag.find_elements(by='class name', value='tag-item')

            if label == '출연:':
                actor = [item.text for item in items]
            elif label == '크리에이터:':
                creator = [item.text for item in items]
            elif label == '장르:':
                genre = [item.text for item in items]
            elif label == '시리즈 특징:':
                char = [item.text for item in items]

        # 관람등급 가져오기
        try:
            maturity_wrapper = driver.find_element(by='class name', value='maturity-rating-wrapper')
            BC = maturity_wrapper.find_element(by='class name', value='maturity-number').text
            age = maturity_wrapper.find_element(by='class name', value='maturityDescription').text
        except NoSuchElementException:
            BC = None
            age = None

        # 방송사 가져오기
        try:
            broadcaster_element = driver.find_element(by='class name', value='broadcaster')
            BC = broadcaster_element.find_element(by='tag name', value='div').text
            year = broadcaster_element.find_element(by='tag name', value='div').text
        except NoSuchElementException:
            BC = None
            year = None

        # 정보를 리스트에 저장
        S_creator.append(creator if creator else None)
        S_actor.append(actor if actor else None)
        S_genre.append(genre if genre else None)
        S_char.append(char if char else None)
        S_BC.append(BC if BC else None)
        S_age.append(age if age else None)
        S_year.append(year if year else None)
    return S_creator, S_actor, S_genre, S_char, S_BC, S_age, S_year

문제점

  • 셀레니움을 이용하여 웹 스크래핑을 하게되면 해당 사이트에 많은 부하를 가하게 된다는 문제가 있다.
  • 너무 빠른속도로 세부정보에 접속하다보면 350개가 넘어갈 즈음 404에러를 목격하게 된다.
    time 모듈을 임포트한 이후 wait를 이용하여 적절한 시간을 주고,
    데이터를 다 저장한 이후에는 db에 없는 작품에 대해서만 세부정보를 접속해야할 것 같다.
profile
땅을 파다보면 흙과 물을 보겠지만, 코드를 파다보면 답이 보일것이다.

0개의 댓글