RaspberryPiでrequests_htmlを使用してハマる

# はじめに
Seleniumを使うのはWebドライバのバージョンを気にしたりと何かと不便。requests_htmlを使用すれば比較的簡単そうと思いRaspberryPi4にインストールしてみましたが結局ハマってしまったのでその記録を残しておきます。
# まずはインストール
```shell
sudo pip install requests_html
```
インストールはpipで行うだけ。いたって簡単です。
# 早速テストスクリプトで試してみるが…
次のようなスクリプトを作成して早速試してみます。
```Python
from requests_html import HTMLSession

session = HTMLSession()
url = "https://www.google.com/"
r = session.get(url)
r.html.render()
```
実行結果
```Python
[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の場所を確認
```shell
which chromium-browser
```
実行結果
```
/usr/bin/chromium-browser
```
そしてこれを元にrequests_html.pyを更新していく。
```shell
sudo vi usr/local/lib/python3.9/dist-packages/requests_html.py
```
変更前
```Python
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'を追加
```Python
self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, executablePath='/usr/bin/chromium-browser', args=self.__browser_args)
```
# さいごに

とりあえずローカルのターミナル上で実行するにはこの方法で上手くいきましたがJupyterを使用した場合は以下のエラーが発生してしまい上手くいかず。
```Python
---------------------------------------------------------------------------
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を使用すると解決できるという記事も見かけましたが上手くいかず。一筋縄ではいきませんな〜。