본문 바로가기
DataScience/Crawling & Scraping

더보기, LoadMore 눌러야 할 때 ( dynamic crawling )

by mkk4726 2023. 7. 4.

https://github.com/mkk4726/recsys-movie

 

GitHub - mkk4726/recsys-movie

Contribute to mkk4726/recsys-movie development by creating an account on GitHub.

github.com

관련 코드는 위의 깃헙 주소에서 확인할 수 있습니다.

(MF/src/crawling-scraping/modules 폴더)


 

 

그림1. LoadMore (IMDb 캡쳐)

데이터를 긁어오다보면 더보기나, Load More과 같은 버튼들을 눌러야할 때가 있습니다.

이를 위해서는 동적크롤링을 사용해야됩니다.

 

 


 

동적크롤링은 Selenium 패키지를 이용하면 쉽게 사용할 수 있습니다.

2023.07.02 - [DataScience/Crawling & Scraping] - Scraping IMDb review data

 

Scraping IMDb review data

https://github.com/mkk4726/CB-movie GitHub - mkk4726/CB-movie: Content-based filtering about movie Content-based filtering about movie . Contribute to mkk4726/CB-movie development by creating an account on GitHub. github.com 이번 글의 코드를 crawlin

mkk4726.tistory.com

 

여기서 만든 함수에 Selenium을 이용해 더보기를 누르는 부분을 추가했습니다.

 

 

get_review 함수 

더보기
def get_review(title_id: str, verbose: bool=False) -> tuple[str, "pd.DataFrame"]:
  
  """IMDb에서 review data를 sraping해오는 func
  + dynamic crawling으로 전체 review 데이터 긁어오기

  Args:
      title_id (str): 영화별 고유 id
      verbose (bool, optional): scraping 과정을 출력할건지 여부

  Returns:
      tuple[str, DataFrame]: title_id, [rating, title, review,	user, date] column을 가진 dataframe
  """
  
  # url = f'https://www.imdb.com/title/{title_id}/reviews?sort=totalVotes&dir=desc&ratingFilter=0'
  # spolier 같은 경우는 접혀있어서 눌러서 봐야함. 따라서 오류가 생긴다. Hide Spoiler옵션 누른 url로 대체
  url = f'https://www.imdb.com/title/{title_id}/reviews?spoiler=hide&sort=totalVotes&dir=desc&ratingFilter=0'

  options = webdriver.ChromeOptions()
  options.add_argument('headless')
  options.add_experimental_option('excludeSwitches', ['enable-logging'])

  # driver = webdriver.Chrome('./chromedriver.exe', options=options)
  driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
  driver.get(url)
  
  load_more_button_xpath = '//*[@id="load-more-trigger"]'  

  # Load More 싹다 누르기
  while True:
    try:
      load_more_button = driver.find_element(By.XPATH, load_more_button_xpath)
      load_more_button.send_keys(Keys.ENTER)
      time.sleep(1)
    except Exception as e:
      # print(e)
      break

  soup = bs(driver.page_source, 'html.parser')
  
  text_list = []
  rating_list = []
  title_list = []
  user_list = []
  date_list = []
  review_df = pd.DataFrame()
  
  try:
    i = 1
    while True:
      main_selector = f'#main > section > div.lister > div.lister-list > div:nth-child({i}) > div.review-container > div.lister-item-content'
      
      text_selector = f'{main_selector} > div.content > div.text.show-more__control'
      text = soup.select(text_selector)[0].text
      
      rating_selector = f'{main_selector} > div.ipl-ratings-bar > span > span:nth-child(2)'
      rating = soup.select(rating_selector)[0].text
            
      title_selector = f'{main_selector} > a'
      title = soup.select(title_selector)[0].text
      
      user_selector = f'{main_selector} > div.display-name-date > span.display-name-link > a'
      user = soup.select(user_selector)[0].text
      
      date_selector = f'{main_selector} > div.display-name-date > span.review-date'
      date = soup.select(date_selector)[0].text
      
      text_list.append(text)
      rating_list.append(rating)
      title_list.append(title)
      user_list.append(user)
      date_list.append(date)
        
      if verbose:
        print(f"{i} is done")
        
      i += 1
  except:
    a = 1 # 아무 의미 없음
    
  if verbose:
    print(f'{title_id} end')
  
  review_df['review'] = text_list
  review_df['rating'] = rating_list
  review_df['title'] = title_list
  review_df['user'] = user_list
  review_df['date'] = date_list
  
  return title_id, review_df

 

 

 

이 중 Selenium을 활용한 코드를 살펴보면,

먼저 driver를 설정해줍니다.

 

url = f'https://www.imdb.com/title/{title_id}/reviews?spoiler=hide&sort=totalVotes&dir=desc&ratingFilter=0'

  options = webdriver.ChromeOptions() # 옵션 설정
  options.add_argument('headless') # 화면에 안뜨게 하기
  options.add_experimental_option('excludeSwitches', ['enable-logging']) # log 안뜨게 하기

  # driver = webdriver.Chrome('./chromedriver.exe', options=options) # 구버전
  driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) # 신버전
  driver.get(url)

 

옵션을 설정해주고, 드라이버 객체를 생성 후 .get 메소드로 url에 접속합니다.

그 후에는 더보기 버튼을 XPath을 이용해 찾고, 눌러주는 과정입니다.

다 누른 후에는 driver.page_source로 html을 가져옵니다.

 

load_more_button_xpath = '//*[@id="load-more-trigger"]'  # 더보기 버튼 XPath

  # Load More 싹다 누르기
  while True:
    try:
      load_more_button = driver.find_element(By.XPATH, load_more_button_xpath) # 버튼 찾기
      load_more_button.send_keys(Keys.ENTER) # 버튼 누르기
      time.sleep(1)
    except Exception as e:
      # print(e)
      break

  soup = bs(driver.page_source, 'html.parser')

 

참고로 XPath를 찾는 방법은, ctrl+shift+I를 누른 후 좌측 상단의 화살표를 눌러 버튼을 클릭합니다.

그 후에 마우스 우클릭 -> copy xpath로 복사해오면 됩니다.

 

XPath 가져오기 설명 캡쳐

 

 

 

댓글