PythonでChromeのSeleniumを利用するまで


Seleniumは利用するDriverや、Versionの不一致、渡すOptionなどなどでよくわからないErrorが大量に発生します。

正直そういったSetup部分にあまり時間をかけたくない方、が大半かと思うので、よく引っかかるであろうポイント、並びにその解決方法をまとめておきます。公式からのダウンロード先も書いておくので、おそらくしばらくはこの方法で対応いただくことできるかと思います。

ちなみにエンジニアとしてあまり良くないですが、とりあえず使ってみてなんとなく動いている的な感じの内容に一部なっております(一通りの罠はふんだと思いますが)。ただ、個人的にこの記事があれば数日の苦労が短縮できたのに...という記事にはなっていると思いますので困っている方には有益かと思います。

実行想定環境

・MacOS、もしくはLinux上でも対応可能です。(Windowsでもほぼ一緒だと思いますが、未検証)。
・GoogleChrome
・Pythonは3.6

前提知識

ドライバーとブラウザー

まず前提条件としてこれを説明しておきます(自分はこれがわかっていなくていろいろな記事を見て混乱したので)。昔にRubyでSeleniumしていたときには意識せずに使えた気がする(というか気にした記憶がない)んですが、Pythonでは何故か結構苦労させられました(なんか違うんですかね)。

SeleniumをPythonで使う際にはSelenium自体のライブラリの他にDriverとBrowserというものが必要になります。
Browserは普段使っているブラウザです。で、Python等プログラムがBrowserを使うために、それをつなぐDriverなるものが必要になります。
Browserはプログラム上でパスを指定しなければ普段使っているアプリのものが読み込まれます(当然サーバ上で動かす場合にはブラウザ入ってないかと思うので要DL)。Driverは普通はないので、公式からDLする必要があります。

Selenium Library -> Driver -> Browser

こんな感じの関係性です。他の記事ですとBrowserの存在があまり触れられてなくて若干混乱してしまう記事もあるので、上記の情報を補足として覚えておいてください、

実際のSetup手順

BrowserとDriverのDLをする

早速にして、最大の嵌るポイントです。
なぜならBrowserのバージョンとDriverの整合するバージョンがもの凄く幅が狭いからです。Driverのマイナーバージョンが0.01ずれてもだめな場合もあり(Browserのほうはメジャーバージョン単位でしか体感問題は発生しません)、しかもエラーメッセージが明確にバージョン違いによるものだと明記されないケースもあります。ここが本当に辛いです。
基本その時点の最新のBrowserとDriverを使えば大丈夫なはずですが、Driverのリリースが遅れることもある気がするので、その場合はBrowserを古いVersionに1つずつ下げて動くか検証します。一度Localで動く組み合わせを手に入れてしまえば基本その部分をいじらなければ大丈夫なので、頑張りましょう。

なので、上で「Browserはダウンロードしなくてもアプリのものが使われる」と書きましたが必ずDLしたものを使うことをおすすめします。アプリのBrowserは自動でアップデートがかかる設定にしていることが多いかと思うので、久しぶりにSelenium動かそうとして動かない、みたいに簡単になります。

各々の公式DL先は以下です

また、サーバ上で動かす場合にはBrowserはheadless(画面を使わないVersionのBrowserのようなもの(英語の意味と矛盾しますが)です。軽量なので用途が限定される場合はこちらがおすすめ)のもので構いません。headlessのブラウザは実行環境でうまく動くものが公式で見つからず以下のGithubから利用しました。ここから引用しているほか記事も2~3あったので、割とその界隈では有名なのかもしれないです。

AwsでEC2などで動かす場合にはheadlessであってもなくても良いと思いますが、Lambdaなどで動かす場合、読込できるサイズの上限があるので、headlessでないと容量的に稼働ができません。ご注意ください。

上記が終われば山場は越えていると思います。

実行の際のOptionの設定

後は簡単です。

$ pip install selenium

上記でseleniumをinstallした後、以下のような形でoptionを指定すれば基本的には動作するはずです。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

# DLしたdriverとbrowserを解凍して、実行ディレクトリに置いてください。
DRIVER_PATH = "./chromedriver"
BROWSER_PATH = "./Chromium.app/Contents/MacOS/Chromium"

class Scraper:
   def __init__(self, dl_path):
       options = Options()
       options.add_argument('--headless')
       options.add_argument('--no-sandbox')
       options.add_argument('--disable-dev-shm-usage')
       options.add_argument('--window-size=1400,1500')
       options.add_argument("--disable-gpu")
       options.add_argument("start-maximized")
       options.add_argument("enable-automation")
       options.add_argument("--disable-infobars")
       options.add_argument("--single-process")
       options.binary_location = BROWSER_PATH
       self.driver = webdriver.Chrome(DRIVER_PATH, options = options)
       self.__set_driver_path(dl_path)

    # headlessでDL処理をするのに必要
    def __set_driver_path(self, dl_path):
       self.driver.command_executor._commands["send_command"] = (
           "POST",
           '/session/$sessionId/chromium/send_command'
       )
       params = {
           'cmd': 'Page.setDownloadBehavior',
           'params': {
               'behavior': 'allow',
               'downloadPath': dl_path
           }
       }
       self.driver.execute("send_command", params=params)

scraper = Scraper("./downloads/")
scraper.driver.get("https://yahoo.co.jp")
...

optionはいろいろなサイトを見て、融合させました。だいたいこれを指定しておけば良いと思います(我ながら適当)。でも実際window-sizeの指定とか漏れるとErrorで動かなかったりします。気になる方はコメントアウトしながら検証してみたり、調べてみたりしてください。

もし、デバッグなどの用途で、実際のBrowserで挙動を見ながら実行したい場合は

options.add_argument('--headless')

をコメントアウトさせれば、対応可能です(Browserがheadlessではない前提ですが)。

また、__set_driver_pathというメソッド内でやっていることは、headlessブラウザの際のダウンロードの挙動を許可するための設定です(headlessはデフォルトで、seleniumでのDL操作を許可していません)。


ここまで設定して動けば後はReference読んだり、一般の記事読みながらなんとかやりたいことができるかと思います。以上になります。

この記事が気に入ったらサポートをしてみませんか?