バスケやデータの雑記帳

バスケやデータ分析について徒然なるままに

Python+Seleniumを使ったスクレイピングその1(2023年10月時点)

今回はスクレイピングに関するメモです。Pythonスクレイピングするといえば、urllib+BeautifulSoupがよく検索で出てきますが、最近のwebページはJavaScriptによってレンダリングされていることが多く、うまくスクレイピングできません。

そこで、Seleniumというブラウザ(ChromeとかFireFoxとか)の自動操作用ライブラリを活用することで、上記の問題をうまくかわしてスクレイピングを行うことができます。数年ぶりに久しぶりに使おうとしたら色々と状況が変わっていたので備忘録として使い方を残しておきます。ついでに、Ajaxなどを使った、動的なwebページに対応するための待機処理に関するTipsもまとめておきます。なお、今回もWindows環境が前提です。

なお、スクレイピング自体が著作権・サーバーへの負荷等の問題が生じうる行為なので、ルール・マナーを守った運用が必要です。自分への戒めも兼ねて、注意事項として記載しておきます。

Seleniumについて、状況が変わっていたこと

数年前の時点ではSeleniumを扱う際に、以下のように別のものをインストールする必要があり、ハマることが多かったです。

しかし、最近バージョンアップされたSeleniumではそれ単体で上記のやりたいことを実現できるようになっていました。今回は4.14.0のバージョンのSeleniumを使って、実際に試していきます。

使い方その1|基本的な使い方

まずはライブラリをインポートします。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

インポートした後は、次のようにコードを記述することで、スクレイピングを行うことができます。 今回はPythonの公式ページにアクセスしてみます。

# アクセスしたいURLを指定
url = "http://www.python.org"

# ブラウザを操作するためのwebdriverを設定
options = Options()
options.add_argument("--headless") # このオプション設定により、ブラウザが表示されなくなる
driver = webdriver.Chrome(options=options) # chromedriverを別でインストールする必要なし

# ブラウザを起動し、URLにアクセス
driver.get(url)

# HTMLの要素を取得
elem = driver.find_element(By.CSS_SELECTOR, "div.introduction")
print(elem.text)

# ブラウザを閉じる
driver.close()
# 実行結果
Python is a programming language that lets you work quickly
and integrate systems more effectively. Learn More

Pythonの公式ページにアクセスし、要素を取得できていることが確認できました。

使い方その2|待機処理を意識した使い方

Ajaxを利用したJavaScriptレンダリングなどがある場合、URLにアクセスしてから(あるいは何かしらSeleniumでwebページの操作を行ってから)HTMLの要素が全てレンダリングされるまでに時間がかかることがあります。

※もちろん、JavaScript以外の理由として、ネット回線の速度やサーバー側の負荷が問題になる場合もあります。

time.sleep(5) など、URLにアクセスしてから要素を取得するまでの間に明示的に待ち時間を設けることも可能ですが、待ち時間が不十分でレンダリングが間に合わずに要素の取得時にエラーとなってしまったり、逆にレンダリングがすぐに終わってしまい、無駄な時間がかかってしまう恐れがあります。

そこで、WebDriverWaitexpected_conditionsを活用することで上記の問題を解決しながらスクレイピングを行うことが可能になります。

それでは、基本的な使い方のときと同様に、まずは必要なライブラリをインポートします。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # 追加
from selenium.webdriver.support import expected_conditions as EC # 追加

WebDriverWaitexpected_conditionsを利用して、先程のコードを書き直してみます。横にコメントが記載されている行が変更点です。

# アクセスしたいURLを指定
url = "http://www.python.org"

# ブラウザを操作するためのwebdriverを設定
options = Options()
options.add_argument("--headless")
driver = webdriver.Chrome(options=options)
wait = WebDriverWait(driver=driver, timeout=30) # 最大待ち時間の設定

# ブラウザを起動し、URLにアクセス
driver.get(url)
wait.until(EC.presence_of_all_elements_located) # HTMLの要素が全てレンダリングされるまで待つ

# HTMLの要素を取得
elem = driver.find_element(By.CSS_SELECTOR, "div.introduction")
print(elem.text)

# ブラウザを閉じる
driver.close()
# 実行結果
Python is a programming language that lets you work quickly
and integrate systems more effectively. Learn More

問題なく動作していることを確認できました!

要素の取得方法について、更に詳細は次の記事でメモしておきます。

bballdatanote.hatenablog.com

参考にさせていただいた記事