現在Discordのチャットルームにスクレイピングしたリンクを貼り付けるなんてプログラムを書いています。 そこでリンク先の画像がほしいなというわけで、ブラウザを起動してスクリーンショットを撮るという動作が欲しくなりました。 普段ならPuppeteerを使ったりするんでしょうけれども、今回はPythonベースなので久しぶりにSeleniumを書くことにしました。

Service chromedriver unexpectedly exited

selenium.common.exceptions.WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: 127

Seleniumやchromedriverのインストールそのものは難しくないのですが、なぜかブラウザが起動せずにWebDriverExceptionというエラーが出てしまうようです。 StackOverflowに興味深い回答がありました。

https://stackoverflow.com/a/49710327

単純に必要なパッケージを出してくれてるのかなと思いきや、chromedriver --versionで起動すると必要なライブラリが足りていないというエラーが表示されるので、それをもとにapt-cache searchで探してみてとのことなので実際にやってみました。

# chromedriver  --version
chromedriver: error while loading shared libraries: libglib-2.0.so.0: cannot open shared object file: No such file or directory

# apt-cache search libglibd-2.0-0
libglibd-2.0-0 - GLib library of C routines - D bindings

# apt-get install libglibd-2.0-0

# chromedriver --version
chromedriver: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory

# apt-cache search libnss3
libnss3 - Network Security Service libraries

# apt-get install -y libnss3

# chromedriver --version
chromedriver: error while loading shared libraries: libX11.so.6: cannot open shared object file: No such file or directory

# apt-cache search libX11
libx11-6 - X11 client-side library

# apt install -y libx11-6

# chromedriver --version
ChromeDriver 84.0.4147.30 (48b3e868b4cc0aa7e8149519690b6f6949e110a8-refs/branch-heads/4147@{#310})

徐々に答えがわかっていくパズルみたいで面白かった。 単純に答えだけ出してくれるのももちろん有り難いですけれども、Chromeのバージョンごとに必要なライブラリも変わってきたりするようなのでこういった方法もあるんだと思うと眉唾ものでしたね。

cannot find Chrome binary

selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary

これで動かせると思った矢先、やっぱり動きませんでした。 このエラーは単純にChromeのバイナリがないといっていますが、chromedriverにはGoogle Chromeが必要ということなので少々面倒ですがインストールする必要があります。

ただスクリーンショットを撮りたいのにGoogle Chromeをインストールするのはだんだん大げさに思えてきたのでChromiumを使うことにしました。 ChromiumならAPTのパッケージとしても提供されているし、バイナリをダウンロードしてくるよりも簡単です。

それでも起動しない

Chromiumに乗り換えたのですがやっぱりうまくいきません。それでもWebの世界は広いもので、ちゃんと答えにたどり着くことができました。

https://stackoverflow.com/a/53073789

起動時にオプションに引数を追加するとうごきました:

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

chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')

Puppeteerでよく見かけるオプションですね。 おそらくDockerとかは関係ないのかもしれませんが、新しいバージョンだとこれらの引数は必要みたいです。