0
1

More than 1 year has passed since last update.

映画.comのレビューをスクレイピングする

Posted at

はじめに

本記事では、映画.comの「劇場版 鬼滅の刃 無限列車編」のレビューをスクレイピングし、csvで出力します。

環境

python 3.10.4
Windows 11 Home
ChromeDriver 114.0.5735.110

必要なライブラリのインストール

seleniumとpandasを使用します。
seleniumはブラウザの操作を自動化するライブラリですが、スクレイピングも行うことができます。今回は「次へ」ボタンの押下も自動化し、全レビューの取得を目的とするため、こちらを使用します。
pandasはデータ解析に使うライブラリです。今回はスクレイピングして取得したデータをcsvで出力する目的で使用します。

pip install selenium
pip install pandas

HTMLの構造

映画.comのレビュー部分は以下のようなHTMLで構成されています。(2023年8月現在)

<!-- このdiv要素がレビューの数だけ並ぶ -->
<div class="txt-block">
 <p class="short">レビュー前半(実際に表示されている部分)
  <span></span>
  <span class="hidden" style="display: none;">レビュー後半(文字数制限で表示できていない部分)</span>
  <a class="more">続きを読む</a>
 </p> 
</div>

<!-- 次へボタンが押せる場合 -->
<a class="next icon-after" href="url">次へ</a>

<!-- 次へボタンが押せない場合 -->
<span class="next disabled icon-after">次へ</span>

作成コード

上記のHTML要素を取得し、スクレイピングを行います。

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import pandas as pd
import time

# ブラウザの起動
chromedriver = "chromedriver.exe"
service = Service(execureviews_path=chromedriver)
driver = webdriver.Chrome(service=service)
url = "https://eiga.com/movie/91918/review/" 
driver.get(url)

# データを取得し、配列に格納する
reviews = []
is_continue = True
while(is_continue):
  text_elems = driver.find_elements(By.CLASS_NAME, "txt-block")
  for text_i in text_elems:
    text = text_i.get_attribute("textContent")
    if '続きを読む' in text:
      text = text.replace("","").replace("続きを読む","")
    if 'ネタバレ! クリックして本文を読む' in text:
      text = text.replace("ネタバレ! クリックして本文を読む","")

    # 配列にデータを格納
    reviews.append(text)

  # 次へボタンが押せなければループを終了、押せるなら押して次のページへ
  if driver.find_elements(By.CSS_SELECTOR, ".next.icon-after.disabled"):
    is_continue = False
  else:
    next_button = driver.find_element(By.CSS_SELECTOR, ".next.icon-after")
    next_button.click()
    time.sleep(2)

# 配列からDataFrameを作成し、csvで出力する
df = pd.DataFrame(reviews, columns=['レビュー'])
df.index.name = 'index'
df.to_csv("無限列車編_レビュー.csv", encoding="utf-8")

#ブラウザの終了
driver.quit()

解説

解説1
text_elems = driver.find_elements(By.CLASS_NAME, "txt-block")
for text_i in text_elems:
  text = text_i.get_attribute("textContent")
  if '続きを読む' in text:
    text = text.replace("","").replace("続きを読む","")
  if 'ネタバレ! クリックして本文を読む' in text:
    text = text.replace("ネタバレ! クリックして本文を読む","")
  • driver.find_elements(By.CLASS_NAME, 'txt-block')
    クラス名が「txt-block」である要素を全て取得
  • text_i.get_attribute("textContent")
    クラス名「txt-block」を持つタグが内部に持っている全文字列を連結して取得
  • replace("…","")
    文字列中に含まれる「…」を削除する

text_i.textとすると、display: none指定されているレビュー後半部分を取得することができませんでした。そのため、text_i.get_attribute("textContent")で、display: none指定されている部分を含めた全文字列を取得し、その後、不要な文字列をreplaceで取り除いています。

解説2
if driver.find_elements(By.CSS_SELECTOR, ".next.icon-after.disabled"):
  is_continue = False
else:
  next_button = driver.find_element(By.CSS_SELECTOR, ".next.icon-after")
  next_button.click()
  time.sleep(2)
  • driver.find_elements(By.CSS_SELECTOR, ".next.icon-after.disabled")
    クラス名「next」、「icon-after」、「disabled」を持つ要素(押せない次へボタン)を取得
  • time.sleep(2)
    2秒間待機

押せない次へボタンがある場合はデータ取得処理を終了し、ない場合は次へボタンを押して次のページに進みます。
2秒間待機を挟むのは、ページが読み込まれる前に要素の検索が実行され、エラーとなるのを防ぐためです。

終わりに

今回は映画.comのレビューをスクレイピングしました。
ボタンを押したら文字を表示する仕組みは、他のwebサイトでも活用されているので、.get_attribute("textContent")は応用が利きそうと感じました。
今後は取得したcsvを使ってテキストマイニングを行う予定です。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1