본문 바로가기
NLP

IMDB 영화 댓글 크롤링 코드

by 볼록티 2019. 11. 28.
728x90
반응형

학교 팀플 과제를 하기 위해 사용할 데이터를 수집하였습니다. 그리 방대한 양은 아니지만, 아래의 코드를 통해 크로링하는데 걸리는 시간은 대충 반나절 정도 걸린 듯 합니다. 초보적인 방법으로 크롤링한거라서 단순합니다. 

데이터는 미국 영화 정보 사이트인 imdb.com 에서 데이터를 크롤링하였습니다. 댓글이 상당히 믿을만하고, 길이도 꽤 길어서 텍스트마이닝 공부할 때 유용하게 쓸 수 있다고 생각합니다. 

이 코드를 그대로 사용하실거라면 우선 chromedrever를 다운받으셔야하고, 압축을 풀고 파일이 있는 절대경로까지 설정을 해주셔야합니다.

 

 

1. 필요한 모듈 설치하기.

 아래에는 필요한 모듈을 설치하는 코드입니다. selenium과 BeautifulSoup을 병행하여 그때그때 사용하였습니다.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time
from datetime import datetime
import re

 

2. 영화에 진입할 링크 가져오기.

 

사이트에서 "Browse by Genre" 배너에 들어온 화면입니다. 여기서 저는 COMEDY, SCI-FI, HORROR, ROMANCE, ACTION 이 다섯개의 장르에 해당하는 영화의 댓글을 수집하였습니다.

 

 

여기는 'ROMANCE'에 들어온 화면입니다. 여기에 랭크 50개의 영화가 있고 각 영화 제목이 하이퍼링크로 되어있는데 이 링크들을 가져오는 것이 아래의 코드입니다. 아래의 5개 링크는 위 화면처럼 각 장르별로 수작업으로 클릭해서 얻은 것입니다. 장르별로 50개만있는게 아니라 더 있기 때문에 위의 화면과 동일한 형식으로 된 페이지이기 때문에 url을 복사해서 아래에 적당히 붙여서 사용할 수 있습니다.

 

함수로 만들지 않은 이유는 중간에 time out 에러가 발생할 수도 있는데, 이는 인터넷 연결문제로 인한 시간초과로 생각할 수 있는데, 왠만하면 에러가 잘나진않습니다. 이 때 지금까지 받은 데이터가 다 날라갈까봐 그냥 for문으로 하였습니다.

 

genre=['comedy','science']#,'horror','romance','action']
comedy_url="https://www.imdb.com/search/title/?genres=comedy&explore=title_type,genres&pf_rd_m=A2FGELUUNOQJNL&pf_rd_p=3396781f-d87f-4fac-8694-c56ce6f490fe&pf_rd_r=GQ23RTBMHB7DF95TKKS2&pf_rd_s=center-1&pf_rd_t=15051&pf_rd_i=genre&ref_=ft_gnr_pr1_i_1"
science_url="https://www.imdb.com/search/title/?genres=sci-fi&explore=title_type,genres&pf_rd_m=A2FGELUUNOQJNL&pf_rd_p=3396781f-d87f-4fac-8694-c56ce6f490fe&pf_rd_r=GQ23RTBMHB7DF95TKKS2&pf_rd_s=center-1&pf_rd_t=15051&pf_rd_i=genre&ref_=ft_gnr_pr1_i_2"
horror_url="https://www.imdb.com/search/title/?genres=horror&explore=title_type,genres&pf_rd_m=A2FGELUUNOQJNL&pf_rd_p=3396781f-d87f-4fac-8694-c56ce6f490fe&pf_rd_r=GQ23RTBMHB7DF95TKKS2&pf_rd_s=center-1&pf_rd_t=15051&pf_rd_i=genre&ref_=ft_gnr_pr1_i_3"
romance_url="https://www.imdb.com/search/title/?genres=romance&explore=title_type,genres&pf_rd_m=A2FGELUUNOQJNL&pf_rd_p=e0da8c98-35e8-4ebd-8e86-e7d39c92730c&pf_rd_r=GQ23RTBMHB7DF95TKKS2&pf_rd_s=center-2&pf_rd_t=15051&pf_rd_i=genre&ref_=ft_gnr_pr2_i_1"
action_url="https://www.imdb.com/search/title/?genres=romance&explore=title_type,genres&pf_rd_m=A2FGELUUNOQJNL&pf_rd_p=e0da8c98-35e8-4ebd-8e86-e7d39c92730c&pf_rd_r=GQ23RTBMHB7DF95TKKS2&pf_rd_s=center-2&pf_rd_t=15051&pf_rd_i=genre&ref_=ft_gnr_pr2_i_1"

WHOLE_URL=[comedy_url,science_url]#,horror_url,romance_url,action_url]

top50 =dict() #장르별 탑 50 영화 버튼(하이퍼링크) 수집
review=dict() #영화 댓글

driver = webdriver.Chrome(r"C:\Users\rok80\Anaconda3\네이버뉴스\chromedriver_win32\chromedriver.exe")
driver.set_page_load_timeout("5")

for i in range(len(WHOLE_URL)):
    url=WHOLE_URL[i]
    time.sleep(3)
    print("get url",genre[i]," 진입 시작")
    driver.get(url)
    print("get url",genre[i]," 진입 완료")
    time.sleep(1)
    time.sleep(1)

    driver.find_elements_by_class_name("lister list detail sub-list")
    soup= BeautifulSoup(driver.page_source)



    h1= soup.find_all("div", class_="lister-list")[0]
    h2= h1.find_all("div", class_="lister-item mode-advanced")
    h3 =[i.find_all("h3", class_="lister-item-header") for i in h2]
    h4= [i[0] for i in h3]
    h5= [i.a['href'] for i in h4]

    top50[genre[i]]=h5

 

top50에는 총 250개의 url이 모여있습니다. 이제 이 url별로 들어가서 댓글을 수집합니다.

 

 

3. 댓글과 평점 수집하기

 

 

driver = webdriver.Chrome(r"C:\Users\rok80\Anaconda3\네이버뉴스\chromedriver_win32\chromedriver.exe")
driver.set_page_load_timeout("20")

for i in range(len(top50)):      #장르(genre)별로 5번 반복.
    count=0
    button= top50[genre[i]]

    for j in button:             # 영화개수 50개 반복
        print(datetime.now())
        print("영화 페이지 진입"+str(i)+" "+str(count))

        driver.get("http://www.imdb.com"+str(j)) # 영화 페이지
        time.sleep(5)

        driver.find_elements_by_name("quicklinksBar")
        soup= BeautifulSoup(driver.page_source)
        time.sleep(0.5)
        h1=soup.find_all("div", class_="subnav")[0]
        time.sleep(0.5)
        h2=h1.find_all("div", id="quicklinksMainSection")[0]("a")[2]['href']
        time.sleep(0.5)

        print("리뷰 페이지 진입"+str(i))
        driver.get("http://www.imdb.com"+h2) # 리뷰 페이지
        count+=1


        for k in range(99999):    #Load More 끝날때까지 반복
            try:
                driver.find_element_by_class_name("ipl-load-more__button").send_keys(Keys.ENTER)
                time.sleep(3)
            except Exception as ex:
                print('더이상 "Load More" 없음', ex)
                break

        print(" 댓글 수집 ")
        try:
            time.sleep(0.5)
            soup= BeautifulSoup(driver.page_source)
            time.sleep(1)
            
            comment=[]
            x= soup.find_all("div", class_="content")

            for h in x:
                try:
                    tmp= h.find_all("div", class_="text show-more__control")[0].text
                    comment.append(tmp)
                except Exception as ex:
                    tmp= h.find_all("div", class_="text show-more__control clickable")[0].text
                    comment.append(tmp)
            
            time.sleep(1)
        except Exception as ex:
            re=['nothing']
            print("댓글없음")
            
            

        print("댓글 평점 수집 ")
        try:
            rating=[]
            x= soup.find_all("div", class_="lister-item-content")
            for h in x:
                try:    
                    a1= h.find_all("span", class_="rating-other-user-rating")[0]
                    a2= a1.find_all("span")[0].text
                    rating.append(a2)
                except Exception as ex:
                    rating.append('99')
                           
            time.sleep(0.5)
            
        except Exception as ex:
            rating= 'nothing'
            print("댓글 평점 없음")

        print(" 영화 이름 추출")
        driver.find_elements_by_class_name("parent") # 영화 이름 가져오기
        time.sleep(1)
        soup= BeautifulSoup(driver.page_source)

        time.sleep(1)
        print(datetime.now())
        print("---수집 댓글, 이름, 평점 저장---")
        h1=soup.find_all("div", class_="parent")[0].text
        h1= re.sub("[\n\t]","",h1)
        h1= h1.replace(" ","")
        review[h1] = [comment,rating,genre[i]] # 영화이름: [[댓글,댓글,댓글,댓글], rating, genre]

 

 

위 화면의 'USER REVIEWS'로 들어 갑니다. 

 

 

 

 

 

 

3번째 코드블럭을 실행하면

위처럼 진행상황을 보여주고, 훗날 크롤링한 데이터는 dictionary형식이고, keys가 영화 이름이고 values에는 댓글들, 댓글에 달린 평점들, 장르로 나타납니다.

 

 

# 수집한 영화 제목

 

# 수집한 영화에 대한 댓글

 

 

# 수집한 영화 댓글에 대한 평점

 

 

 

수집할 때 주의할 점. 내가 본 html형식이 다가 아닐 수도 있기 때문에 스몰 데이터로 충분히 규칙성을 확인해보고, 결과값도 길이를 비교해서 딱딱 맞게 수집되었는지 확인을 해봐야한다. 아니면 몇시간 동안돌리고 나서 다시 돌려야한다..🤦‍♂️

 

위의 코드처럼 댓글의 개수와 평점의 개수가 같은지 확인해보고 잘 수집되었는지 확인해보는게 반드시 필요하다는 것을 느꼈습니다.

728x90
반응형

'NLP' 카테고리의 다른 글

구글 비트코인 뉴스 크롤링  (4) 2019.11.29
구글 검색 뉴스 감성분석  (0) 2019.11.29
코사인 유사도를 활용한 유사 문서 검색  (0) 2019.11.22
뉴스 기사 분류  (0) 2019.11.22
크롤링 4  (0) 2019.11.21

댓글