仮想環境のarm64 Linuxの上で動かすのはやっぱりChromiumだった件
以前、以下の記事を書きました。
簡単に説明すると、私の使用しているmacOSの上でarm64 Linuxの仮想環境を動かし、その中でx86_64のChromeを動かす方法を説明したものでした。
しかし、これにはいくつかの問題が含まれていました。まずは、仮想環境のソフトウェアとしてUTMを使用したのですが、その上で動かすAppleが提供しているフレームワークであるAVF(Apple Virtualization Framework)が安定していませんでした。安定していないというのは語弊があるのですが、どちらかといえば、AVFで動かすRosetta for Linuxが安定しておらず、昨日までなんの問題もなく動いていたx86_64のChromeを今日動かすとエラーで動かないというのがしょっちゅう起こってしまいました。
そこで、UTMに変わる仮想環境としてLimaを使用し、使ってみたのですが、バージョンアップした途端、動きが怪しくなったなど、こちらも問題が出てきました。
仕方ないので、根本から考え直そうと思い、Rosetta for Linuxを使用しない方法を検討し、単純ながら解決する方法が見つかりましたので、ご紹介します。
結論を先に言ってしまえば、Google ChromeではなくChromiumを使用するということです。オープンソースのChromiumが先に開発され、それをベースに自動アップデート機能、Googleへの利用統計送信機能等、Google独自の機能が追加されたのち、Google Chromeとして公開されます。
つまり、基本的な機能においては、Google ChromeもChromiumも違いはないため、Webスクレイピングするのであれば、Google Chromeを無理に使わなくてもいいということです。
この単純なことに気がつくまでかなり時間をかけてしまいました。自分自身で情けなくなります。そこからは簡単で、ChromiumとWebDriverの関係や、アップデートの仕方、Seleniumからの呼び出し方法などを確認しました。
Google Chromeの代替ブラウザとして、Chromiumを使用するということは当然、arm64版が存在するということです。インストールも単純です(以下はDebian、Ubuntuの例です)。
sudo apt install chromium chromium-driver
1つ目に指定しているのはChromium、2つ目がChromiumのWebDriverを指定している箇所です。Google Chromeの問題は、自動アップデートが勝手に動いてしまい、Google ChromeのバージョンとWebDriverのバージョンが合わなくなるという問題がありました。そのため、SeleniumにはWebDriver Managerという仕組みが途中から導入され、Chromeに適合するWebDriverを自動的に見つけてくれるようになりました。それについては、最初の記事に書いている通りです。
Chromiumを使用すると、自動アップデートが勝手に動くことがないため、Chromiumをアップデートするタイミングで、同時にWebDriverもアップデートできるため、バージョンの整合性がなくなるという問題自体発生しなくなります。
しかし、SeleniumからChromiumのWebDriverを呼び出すにはどうすればいいのかという問題が残ります。これについては、以下のようなコードで解決することができます。
import time
from selenium.webdriver.chrome.service import Service
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Webスクレイピング用のWebブラウザの起動
options = webdriver.ChromeOptions()
options.add_argument('--lang=ja-JP')
options.add_experimental_option('prefs', {'intl.accept_languages': 'ja'})
# Chromiumの起動
driver = webdriver.Chrome(options=options, service=Service('/usr/bin/chromedriver'))
driver.set_page_load_timeout(60)
driver.implicitly_wait(15)
driver.get('https://www.google.com/')
time.sleep(10)
element = driver.find_element(By.NAME, 'q')
element.send_keys('Python')
element.send_keys(Keys.ENTER)
time.sleep(10)
# Webブラウザの終了とWebDriverのインスタンス終了
driver.close()
driver.quit()
上の記事と同様、WebDriverがある場所を直接指定するという方法です。ChromiumのWebDriverをaptでインストールすると、/usr/bin/chromedriverがWebDriverのパスとなるため、それを直接指定します。
これで問題なくGoogle Chromeの代わりにChromiumが動きます。ただし、1点だけ注意が必要です。Google Chromeの時には問題なかったのですが、読み込むページによっては、英語のページを返してくるものがあるため、以下のコードを追加する必要がありました。
options.add_experimental_option('prefs', {'intl.accept_languages': 'ja'})
これを指定することで、HTTP のAccept-Languageリクエストヘッダーに日本語を要求するようにします。Google Chromeの場合は、以下のコードだけで大丈夫だったのですが、どうもChromiumはこれだけではダメだったので、Accept-Languageの指定も加えてみました。
options.add_argument('--lang=ja-JP')
一応、これで問題なくWebスクレイピングが可能となりました。
ただし、前回、Windows+WSLで感動した開発環境を真似するということで紹介した、XQuartzを使用したテスト方法が完全にできなかったことをお伝えします。
macOS側にXQuartzを導入し、~/.ssh/configなどを書き換えることにより、Linuxで動くGUI画面をmacOS側に表示させることができるというテスト方法ですが、失敗に終わりました。前回のような単純なテスト内容、画面を表示し、検索をするなどのようなものはできたのですが、もう少し細かな制御、ユーザー名、パスワード、ワンタイムパスワードの入力云々、などをしようとすると、何故か、パスワードがユーザー名の欄に入力されてしまったり、うまくボタンをクリックできなかったりと、色々と見直したものの完全に真似することができませんでした。
この辺りは、もう少し調査が必要なようです。仕方ないので、UTMをヘッドレス(画面表示なし)で動かさず、単純にLinuxのGUI画面を表示して、テストするときはそちらを使用するというテスト方法に切り替えて何とか開発環境を作り終えることができました。
いくつか課題はあるものの(仮想環境を通常時はヘッドレスで動かして、必要に応じてRDPで画面を表示するなど)、何とかLinux仮想環境を作り終えました。しかし、やはりWindows+WSLと同等の開発環境には程遠いので、今後も色々と模索していきたいと思います。
#Mac
#macOS
#Linux
#Debian
#Ubuntu
#UTM
#AVF
#AppleVirtualizationFramework
#X11
#仮想化
#WSL
#プログラム
#Python
#初心者