PythonのSeleniumを利用してスクレイピングを実践した際の備忘録です。
スクレイピングを初めて行う方はコードを書き始める前に、スクレイピングの危険性を知っておきましょう。以下の記事を一読推奨です。
岡崎市立中央図書館事件
岡崎市立中央図書館事件 - Wikipedia
さて、スクレイピングを行う際に重要となってくるのは待機処理です。
スクレイピングにおける待機処理は、上の事件のようなスクレイピング先サイトへの過度なアクセスによる負荷を軽減したり、ページ読み込み時間の確保に必須の処理です。
さらに、最近のWebサイトは動的なページも多く、待機時間を設けない場合ハイスペックなPCでない限りまともにスクレイピングができません。
この記事では、Seleniumを用いてスクレイピングをするための待機処理の書き方についてまとめていきます。
スクレイピングについてググってみると、とりあえずsleep.time()を使っとけ系記事が度々見受けられますが、sleep.time()は指定時間待つだけなのでスクレイピング時に対応できない場面があります。
Seleniumにはちゃんとした待機処理のメソッドがあります。
それらを知っておくことで効率よくスクレイピングが行えるようになります。
ぜひ、この記事を読んでtime.sleep()から卒業しましょう!(sleepを使わないとは言ってない)
Seleniumの待機処理が必要なわけ
Seleniumを利用してスクレイピングする上で待機処理が必要な理由は、Seleniumの処理速度が速すぎてページ応答が来る前に次の処理を実行してしまうためです。
そのため、待機処理を書いてページの読み込む時間を確保することが重要です。
また、スクレイピング先に負荷をかけ過ぎないようにスクレイピングの頻度を調整するためにも待機処理が必要です。
アクセスが多すぎるとアクセス制限されかねないですし、前述のような事件を起こしかねません。
では待機処理が必要になるのはスクレイピングのどの手順なのでしょうか、疑問になりますよね。
スクレイピングの大まかな手順をまとめると以下の通り。
- Seleniumでブラウザ起動
- スクレイピング先WEbページへアクセス
- 取得したいデータをスクレイピング
- データの保存
結論からいうと待機処理が必要なのは、手順2と3の間だけです。
サイトを読み込み終えるまでに待機処理がないと、スクレイピング先サイトのhtmlファイルが読み込まれず、スクレイピングが行えません。
他の手順は全て自分のPC内で完結する処理なので待ち時間は必要ありません。
また、スクレイピング頻度調整の待機処理はtime.sleep()でも問題ないです。
time.sleep()のデメリット
待機処理によく用いられるtime.sleep()は、( )内に指定した秒数だけ処理を中断して待機することができます。
具体的には以下のように書きます。
1 2 3 4 5 |
import time time.sleep(5) #5秒間処理を中断 |
time.sleep()はスクレイピングの頻度を下げるときには有効ですが、Webページが読み込まれるまで待機するときには適しません。
なぜなら、Webページが読み込まれる時間は不定であるからです。Webページにアクセスしてから1秒後に表示されるときもあれば10秒後に表示されることもあります。
この時間は自分のPCの処理性能だけでなく相手側のPC、通信環境の影響も受けるので、正確に推定するのは難しいです。
要は使い分けることが重要で、単純な処理の待機を実装したいならtime.sleep()で問題なし。
Webページ読み込み時はSeleniumの待機処理メソッドを使うべし、です。
Seleniumの待機処理メソッド一覧
Seleniumの待機処理メソッドを利用することで、ページが読み込まれるまでの時間確保が簡単かつ最適に実装できます。
備忘録なので、汎用性の高そうなのをピックアップしてまとめます。
Seleniumの待機処理メソッド(これ以外にもまだあります)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Firefox() driver.get("http://somedomain/url_that_delays_loading") #Webドライバーのタイムアウト時間を10秒に設定 wait = WebDriverWait(driver, 10) #title_contains() #指定した文字列がページタイトルに含まれるまで待機 element = wait.until(EC.title_contains("3D")) #presence_of_element_located(locater) #指定した要素がDOM上に現れるまで待機 element = wait.until(EC.presence_of_element_located(By.CSS_SELECTOR, "CLASSセレクタ")) #visibility_of_element_located(locater) #指定した要素がDOM上に現れ, かつheight・widthが0以上になるまで待機 element = wait.until(EC.visibility_of_element_located(By.ID, 'id属性値')) #visibility_of_all_elements_located #ページの全要素がDOM上に現れ, かつheight・widthが0以上になるまで待機 element = wait.until(EC.visibility_of_all_elements_located) #element_to_be_clickable(locater) #指定した要素がクリックできる状態になるまで待機 element = wait.until(EC.element_to_be_clickable(By.XPATH, "XPATH")) |
これらを書くことでSeleniumがページを読み込み必要なデータがそろうまでの待機処理を実現できます。
スクレイピング時間を最適化することが理想ですが、とりあえず動くコードを書くためには、visibility_of_element_located()メソッドを使うのがおすすめです。
ページの全要素が読み込まれるまで待機することができるため汎用性が高く、スクレイピングしたいデータが決まっていない場合も対処できます。
上記以外のSeleniumの待機処理メソッドを知りたい方は以下のリンク先のサイトがおすすめです。
Selenium Python について、Baiju Muthukadan氏のまとめたサイト
5. Waits — Selenium Python Bindings 2 documentation
上記サイトをあずみ.net氏が日本語訳したサイト
5. 待機 — Selenium Python Bindings 2 ドキュメント
Pythonクローリング&スクレイピング ―データ収集・解析のための実践開発ガイド―
Pythonでスクレイピングしたい人におすすめ。Kindle版なら3000円ほどで購入可能です。