はじめに
Seleniumを使うのはWebドライバのバージョンを気にしたりと何かと不便。requests_htmlを使用すれば比較的簡単そうと思いRaspberryPi4にインストールしてみましたが結局ハマってしまったのでその記録を残しておきます。
まずはインストール
sudo pip install requests_html
インストールはpipで行うだけ。いたって簡単です。
早速テストスクリプトで試してみるが…
次のようなスクリプトを作成して早速試してみます。
from requests_html import HTMLSession
session = HTMLSession()
url = "https://www.google.com/"
r = session.get(url)
r.html.render()
実行結果
[INFO] Starting Chromium download.
100%|████████████████████████████████████████| 109M/109M [00:12<00:00, 8.61Mb/s]
[INFO] Beginning extraction
[INFO] Chromium extracted to: /home/pi/.local/share/pyppeteer/local-chromium/588429
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.9/dist-packages/requests_html.py", line 586, in render
self.browser = self.session.browser # Automatically create a event loop and browser
File "/usr/local/lib/python3.9/dist-packages/requests_html.py", line 730, in browser
self._browser = self.loop.run_until_complete(super().browser)
File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/usr/local/lib/python3.9/dist-packages/requests_html.py", line 714, in browser
self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, args=self.__browser_args)
File "/usr/local/lib/python3.9/dist-packages/pyppeteer/launcher.py", line 307, in launch
return await Launcher(options, **kwargs).launch()
File "/usr/local/lib/python3.9/dist-packages/pyppeteer/launcher.py", line 148, in launch
self.proc = subprocess.Popen( # type: ignore
File "/usr/lib/python3.9/subprocess.py", line 951, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/usr/lib/python3.9/subprocess.py", line 1823, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 8] Exec format error: '/home/pi/.local/share/pyppeteer/local-chromium/588429/chrome-linux/chrome'
renderを実行した後にOS Errorが発生。ふむ…、素直に実行させてくれないらしい。
対処法
調べてみるとrenderの初回実行時にpyppeteerがChromiumをダウンロードするらしいがその際にintel64版をダウンロードしてしまっていることが原因(Raspberrypiはarm)とのこと。解決策は元々RaspberryPiにインストールされているChromiumに向き先を変えるということで解決するらしい。ということで以下を実施。
requests_html.pyを修正
まずはデフォルトで入っているChromiumの場所を確認
which chromium-browser
実行結果
/usr/bin/chromium-browser
そしてこれを元にrequests_html.pyを更新していく。
sudo vi usr/local/lib/python3.9/dist-packages/requests_html.py
変更前
self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, args=self.__browser_args)
変更後
※requests_html.pyのpyppeteer.launchを呼び出す箇所にexecutablePath='/usr/bin/chromium-browser'を追加
self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, executablePath='/usr/bin/chromium-browser', args=self.__browser_args)
さいごに
とりあえずローカルのターミナル上で実行するにはこの方法で上手くいきましたがJupyterを使用した場合は以下のエラーが発生してしまい上手くいかず。
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-5-83d95e0e8a07> in <module>
----> 1 r.html.render(timeout=60.0)
/usr/local/lib/python3.9/dist-packages/requests_html.py in render(self, retries, script, wait, scrolldown, sleep, reload, timeout, keep_page)
584 """
585
--> 586 self.browser = self.session.browser # Automatically create a event loop and browser
587 content = None
588
/usr/local/lib/python3.9/dist-packages/requests_html.py in browser(self)
727 self.loop = asyncio.get_event_loop()
728 if self.loop.is_running():
--> 729 raise RuntimeError("Cannot use HTMLSession within an existing event loop. Use AsyncHTMLSession instead.")
730 self._browser = self.loop.run_until_complete(super().browser)
731 return self._browser
RuntimeError: Cannot use HTMLSession within an existing event loop. Use AsyncHTMLSession instead.
nest_asyncioを使用すると解決できるという記事も見かけましたが上手くいかず。一筋縄ではいきませんな〜。