PythonでSeleniumを使ってWebスクレイピングする基本について解説します。
Contents
SeleniumによるWebスクレイピングの基本
Webスクレイピングとは、Webサイトで公開されている情報から特定の情報を抽出してきて活用する技術のことを言います。
似たような言葉にクローリングという言葉がありますが、クローリングはWebを巡回してWebページを収集してくることを言います。クローリングするプログラムをクローラーと言いますが、代表的なものにGoogleの検索エンジンがインデックスを作るためのクローラーがあります。
スクレイピングは「こすること」「削ること」といった意味があるので、必要な情報を明示的に抽出するという意味があるのでクローリングとは少し異なります。
PythonでWebスクレイピングとなるとよく出てくるのが「Beautiful Soup」と「Selenium」です。本記事ではSeleniumでWebスクレイピングをするにあたっての基本を紹介します。
Seleniumは本来はテストの自動化ツールで、Webブラウザの操作を自動化することでWebシステムのテストを人手ではなくプログラムで実行できるものです。
例えば健全性テスト項目を実行するテストプログラムをSeleniumを使って用意しておけば、システム改修時に改修箇所以外の主要なプログラムが一通り正常に動作するかを簡単に確認できます。その技術の中でWeb構造を取得できるため、Webスクレイピングの方法としても使用されることがあります。
なお、本記事ではOSはWindowsで、ブラウザとしてはGoogle Chromeを用いた環境での使用方法を紹介をします。
Beautiful Soupの使用方法は「Beautiful SoupによるWebスクレイピングの基本」にまとめていますので興味があれば参考にしてください。
Webドライバーの取得
SeleniumをWindowsで使用する場合には、Webドライバーであるchromedriverが必要です。Webドライバーは、プログラムがブラウザを操作するためのインタフェースを提供してくれるものです。なお、FireFoxではgeckodriverが該当します。
ChromeのWebドライバーであるchromedriverは、こちらから入手できます。ご自身が使用しているChromeのバージョンにあわせたドライバーを取得します。最新安定バージョンなどは以下のようなリンクがありますが、他のバージョンの場合は「Downloads」から探してください。
今回の例では「ChromeDriver 100.0.4896.60」で紹介しますが、他のバージョンも同じです。
リンク先には以下のようなファイルがありますので「chromedriver_win32.zip」をクリックしてダウンロードしてください。
zipファイルを解凍すると「chromedriver.exe」がありますので、これから実行するPythonファイルと同じフォルダまたは任意のフォルダに配置しておいてください。
Chromeのバージョンは、Chrome右上から[設定]をクリックし、[Chromeについて]という項目をクリックすると確認することができます。
Seleniumのインストール
SeleniumをPythonで使用するには、以下のようにpipでインストールをしてください。
pip install selenium
Seleniumを使ってみる
今回はPython公式ページからhtmlを取得してきて、情報を抽出してみることを考えてみようと思います。
from selenium import webdriver from selenium.webdriver.chrome import service from selenium.webdriver.common.by import By # ドライバーのパスを設定(今回は実行ファイルと同じとしてある) CHROME_DRIVER_PATH = "./chromedriver.exe" # Webドライバーを用意する chrome_service = service.Service(executable_path=CHROME_DRIVER_PATH) browser = webdriver.Chrome(service=chrome_service) # 対象のWebページを開く browser.get("https://www.python.org/") # タイトルを取得してみる print(browser.title, "\n") # 文字列を取得してみる elem_intro = browser.find_elements(by=By.CLASS_NAME, value="introduction") print(elem_intro[0].text) # ブラウザを閉じる browser.close()
【実行結果】 Welcome to Python.org Python is a programming language that lets you work quickly and integrate systems more effectively. Learn More
※実行結果は実行時点での参照先ページ構成により異なる又は取得失敗する可能性があります。
上記プログラムのファイル名をselenium.pyという名前にしてしまうと以下のようなエラーになってimportに失敗します。ファイル名は別の名前にしましょう。
ImportError: cannot import name 'webdriver' from partially initialized module 'selenium'
【詳細解説】
以降で、各部分について詳細を説明していきます。まずは、seleniumの必要な項目を以下のようにimportします。
from selenium import webdriver from selenium.webdriver.chrome import service from selenium.webdriver.common.by import By
次にChromeを操作するためのWebドライバーを以下のように用意し、対象Webページをgetメソッドで開きます。ここまで実行されるとChromeが自動で起動されることが分かるかと思います。
今回は、Pythonプログラムと同じフォルダにchromedriver.exeを配置したので以下のようになっていますが、任意のフォルダに配置した場合にはそのパスをCHROME_DRIVER_PATHに指定してください。
# ドライバーのパスを設定(今回は実行ファイルと同じとしてある) CHROME_DRIVER_PATH = 'chromedriver.exe' # Webドライバーを用意する chrome_service = service.Service(executable_path=CHROME_DRIVER_PATH) browser = webdriver.Chrome(service=chrome_service) # 対象のWebページを開く browser.get('https://www.python.org/')
具体的な情報取得の部分は後述しますが、最後には以下のようにclose()でブラウザを自動で閉じています。この部分を省略又はコメントアウトするとブラウザは開いたままになります。
# ブラウザを閉じる browser.close()
次に、具体的に各情報を取得している部分について見てみましょう。
要素を指定して情報を取得する
要素を指定する方法について紹介します。まず、titleタグのような一部の項目については、getメソッドで画面を開いた際にプロパティとして設定されていて以下の部分のように簡単に取得できます。
# タイトルを取得してみる print(browser.title, '\n')
次に、その他の要素を取得する方法についてですが、以下の部分のようにfind_elementsメソッドを使用します。
# 文字列を取得してみる elem_intro = browser.find_elements(by=By.CLASS_NAME, value='introduction') print(elem_intro[0].text)
find_elementsでは、by引数でどういった要素を取得するかを指定し、value引数で具体的な値を指定します。上記の例では、’class’が、’introduction’の要素を取得してくるように指定しています。
by引数で指定できるものは、最初にimportしているByクラスに定義されていて「By.ID」「By.TAG_NAME」「By.CLASS_NAME」や後述する「By.XPath」等を指定できます。今回はクラス名を指定しましたが、IDやタグ名を指定した取得も同様にできます。
複数の要素が存在する場合があるため、find_elementsメソッドからはリストが返却がされます。そのため、今回の例では[0]と指定して表示をしています。具体的な内容については、textプロパティで取得ができます。
XPathの利用
上記で要素を指定しながら情報を取得する方法を見ましたが、seleniumでは、XPathを使用することができます。
XPathとは「XML Path Language」のことでXML/HTMLのドキュメントの要素や属性値などを指定するための言語です。
上記例をXPathを使用して記載すると以下のようになります。
from selenium import webdriver from selenium.webdriver.chrome import service from selenium.webdriver.common.by import By # ドライバーのパスを設定(今回は実行ファイルと同じとしてある) CHROME_DRIVER_PATH = "./chromedriver.exe" # Webドライバーを用意する chrome_service = service.Service(executable_path=CHROME_DRIVER_PATH) browser = webdriver.Chrome(service=chrome_service) # 対象のWebページを開く browser.get("https://www.python.org/") # タイトルを取得してみる print(browser.title, "\n") # 文字列を取得してみる elem_intro = browser.find_elements( by=By.XPATH, value='//*[@id="touchnav-wrapper"]/header/div/div[3]' ) print(elem_intro[0].text) # ブラウザを閉じる browser.close()
XPathを使用する際には、by引数にBy.XPATHを設定し、value引数にXPathの文字列を記載します。このように記載を変えて実行してみてもらえば、同じ実行結果になることが分かるかと思います。
なお、具体的なXPathの文字列については、XPathの具体的な記法が分からなくてもChromeを使って簡単に取得することができます。対象のWebページで[右クリック]-[検証]をクリックするとHTMLのコードが表示されます。矢印のアイコンをクリックして、実際の画面上を選択すると該当するHTMLの位置が分かるのでとても便利です。
XPathを取得したい場合は、該当するHTMLのコード上で[右クリック]-[Copy]-[Copy XPath]をクリックすることでXPathの文字列をコピーして取得することができます。
[補足] Serviceオブジェクトの利用について
上記で紹介したコードでは、Webドライバーを用意する際にserviceという引数にWebドライバーのあるパスを設定したサービスオブジェクトを指定していました。
seleniumのgetメソッドでは、以下のように直接Webドライバーのパスを指定することも可能で普通に動作します。
# Webドライバーを用意する browser = webdriver.Chrome('chromedriver.exe') # 対象のWebページを開く browser.get('https://www.python.org/')
しかし、この方法だと以下のようにDeprecationWarningという警告が表示されます。
DeprecationWarning: executable_path has been deprecated, please pass in a Service object
警告であるため、この方法でも動作自体はしますが、毎回出るのも少し邪魔なので上記のような書き方をして警告が出ている人は、サービスオブジェクトを使用した方法に変えて使ってみてください。
Seleniumによる画面操作
冒頭でも記載しましたが、Seleniumは本来、テストの自動化ツールです。Webスクレイピングとして情報を取得してくるのとは違ってブラウザを操作するというイメージについても少し持って頂こうかと思います。
Python公式ページを開き、ダウンロードページへのボタンをクリックしてダウンロードページへ遷移する例を見てみましょう。
from selenium import webdriver from selenium.webdriver.chrome import service from selenium.webdriver.common.by import By # ドライバーのパスを設定(今回は実行ファイルと同じとしてある) CHROME_DRIVER_PATH = 'chromedriver.exe' # Webドライバーを用意する chrome_service = service.Service(executable_path=CHROME_DRIVER_PATH) browser = webdriver.Chrome(service=chrome_service) # 対象のWebページを開く browser.get('https://www.python.org/') # ダウンロードボタンを取得する download_button = browser.find_elements(by=By.XPATH, value='//*[@id="downloads"]/a') # ダウンロードボタンをクリックして遷移する download_button[0].click()
ダウンロードボタンの位置はXPATHにて指定しています。
上記を実行すると画面が開くとともにダウンロードページへ遷移できることが分かるかと思います。
他にもsend_keysメソッドを指定して値を入力したりもできるので、ログイン画面でIDとパスワードを入れてから、ログインボタンをクリックするというようなことも容易にできます。
Seleniumは本来このようにWebページを操作してテストをするためのものです。開発者としては試験を自動化して、改修時の確認工数を減らすといったことができてとても便利ですのでSeleniumのテスト自動化について色々調べてみてもらえたらと思います。
上記で紹介しているソースコードについてはgithubにて公開しています。参考にしていただければと思います。