[Python3]Seleniumでスクレピング。基本操作、問題に陥った時の対応策のまとめ

最近スクレピング案件が増え、どんどんSeleniumの知識が増えている今日この頃、、

今回はそんな培ったスクレピング知識、困ったときの対応策などを記事にしてまとめてみました!

目次

Seleniumとは

Selenium は、Web ベースアプリケーションのテスト自動化の高速開発をサポートした堅牢なツール群です。Selenium は、Web アプリケーションのテストニーズに特化したテスト機能を豊富に備えています。テスト操作の柔軟性は高く、UI 要素を特定したり、テストの期待値と実際のアプリケーションの動作を比較したりするための多数のオプションを利用できます。
(oss.infoscience.co.jp/seleniumhq/docs/01_introducing_selenium.htmlより引用)

元々はテスト自動化のためのツールだったようで、柔軟にカスタマイズができることからスクレピングする上で非常に有効なツールです。
ブラウザの要素を操作し、データ取得、ページ遷移などさまざまな動きをすることができます。またサポートしているブラウザも多く

  • Firefox 2~3
  • IE 7~8
  • Safari 2~3
  • Opera 8~9
  • Google Chrome

などがあります。

簡単なスクレピング例

今回はPython3+Selenium+Chromeブラウザを使ってI-SEEDブログを自動操作、スクレピングしてみたいと思います。

環境

  • Ubuntu 18.04.3
  • Python 3.6.9
  • selenium 3.141.0
  • chrome 79.0.3945.88
  • chromedriver 78.0.3904.70
  • chromedriver_binary 78.0.3904.70.0

chromedriver_binaryはchromedriverのパスを自動で通してくれます。

準備

seleniumにはChromeブラウザのバージョンにあったchromedriverインストール必要があります。

またchromedriver_binaryもchromedriverと同じバージョンでインストールしてください。

$ pip install selenium
$ pip install chromedriver_binary

実践

import chromedriver_binary
from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument('--headless') #ヘッドレスで起動する

driver = webdriver.Chrome(options=options)
driver.get('https://iseed.jp/blog/') #ページ遷移
driver.save_screenshot("./iseed-blog.png") #現在のページをスクリーンショットする
text = driver.find_element_by_xpath('//*[@id="container"]/div[1]/section/div[1]/div/div/h2').text #ページ内の要素を取得

print(driver.title) #ブログ – 株式会社I-SEED(アイシード)|大阪・心斎橋のWEB制作集団
print(text) #BLOG
driver.quit()#全てのウィンドウを閉じる

以上のコードだけで、簡単にスクリーンショット、サイトタイトルが取得できます。

コマンドについてはドキュメントに色々記載されているのでここでは割愛します。

次は僕が実際遭遇した問題の対応策をまとめています。

陥った問題・対策

エラーが出たときに、Chromeプロセスが止まらない

Chromeのプロセスが継続して動いていると、コードを修正してChromeを動かしたときに正常に動作してくれない場合があります。

import chromedriver_binary
from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://iseed.jp/blog/')

print(driver.title)

print(test) #ここでエラー

driver.quit()

このままではdriver.quit()がまで行かず、プロセスが残ります。

 8484 pts/0    00:00:00 chromedriver
 8490 pts/0    00:00:01 chrome <defunct>

killコマンドなどでプロセスを削除して対応はできますが、なにかとめんどくさい。。。

そんなときは例外処理で対応します。

import logging
import chromedriver_binary
from selenium import webdriver

try:
    driver = webdriver.Chrome()
    driver.get('https://iseed.jp/blog/')

    print(driver.title)
    print(test) #ここでエラー

except:
    logging.error("traceback",exc_info=True)

finally:
    driver.quit()

finallyにdriver.quit()をおいて必ず最終的にChromeを終了させます。
エラー内容も見れるようloggingを追加しています。

.textで取得すると文字が空になる

CSSプロパティがdisplay: noneになっているタグなどを取得する際に起きました。

driver.find_element_by_xpath('//*[@id="hoge"]/div[1]/section/div[1]/div/div/h2').text

そんなときは.get_attribute(“textContent”)で回避できます。

driver.find_element_by_xpath('//*[@id="hoge"]/div[1]/section/div[1]/div/div/h2').get_attribute("textContent")

.textではページ上に表示されている(見える)要素しか取得してくれないので、.get_attribute(“textContent”)を使いましょう。

Qiita
Seleniumでタグに囲まれた文字列を.textで取得すると空文字が返ってくる - Qiita 背景 Webブラウザの自動操作をするために、タグで囲まれた文字列をtextメンバで取得しようとしたのですが、 下記の実装例のように実装すると、"TEXT1" という文字列が取得...

Sleepしすぎて処理が遅い

要素を取得する際にページ遷移など、ページの表示を待たなければならないとき、sleepを使いがちです。
しかし、そのsleepで設定したタイムは余分な時間ができる可能性があります。

そんなときはオプションで予め最大のスリープ時間を設定しましょう。

driver.implicitly_wait(5)

上のコードで各要素が見つかるまで5秒待ちます。

Chromeが重く、メモリクラッシュが起きる

DockerやHerokuからChromeを動かす機会があるときに起こる問題です。
Chromeの処理は非常に重く、デフォルトのDockerやHeorkuではメモリ不足が原因で正常に動作してくれない場合があります。

そんなときには以下のオプションをを追加しましょう。

options.add_argument('--disable-dev-shm-usage')

デフォルトでDockerやHeorkuでは/dev/shmにメモリを使用するようで64MB、512MBでプログラムによっては足りない場合があります。

上のオプションを使用することで/tmpを使用するようになり、メモリ不足を回避できるようです。

この記事の著者

I-SEEDブログ編集部のアバター
I-SEEDブログ編集部

システム開発やWeb制作・デザイン、Webマーケティングを強みに持つI-SEEDスタッフが、さまざまなノウハウや最新情報をお届けします。

CONTACT/ お問い合わせ

システム開発やWeb制作・デザイン、Webマーケティングに関するご質問やご相談はこちらから。

お問い合わせする

ESTIMATE/ 料金シミュレーター

Web上で簡単なお見積もりが可能です。シミュレーション結果をもとにお問い合わせいただくことも可能ですので、お気軽にご相談ください。

Web見積もりをする
目次