歩いたら休め

なんでこんな模様をしているのですか?

【Python】Requests-HTMLでスクリーンショットを撮る

Pythonの著名なHTTPクライアントライブラリのrequestsに似たAPIで、シンプルなAPIスクレイピングに必要な機能が実装されています。実際には他のいくつかのライブラリをラップしています。

Requests-HTML: HTML Parsing for Humans (writing Python 3)! — requests-HTML v0.3.4 documentation

以下のようなコードで、簡単にChroniumを自動でダウンロードしてブラウザでレンダリングして、HTMLをパースして必要な情報を取り出すことができます。Chroniumの操作は内部ではpyppeteerを利用しているようです。

r = session.get('http://python-requests.org/')

>>> r.html.render()

>>> r.html.search('Python 2 will retire in only {months} months!')['months']
'<time>25</time>'

今回試したこと

今回私はE2Eテストのようなことを行いたく、

という利用用途でした。ドキュメントには陽にその方法が書かれていなかったのですが、以下のISSUEを参考に、一応は実装することができました。screenshotのメソッドが非同期の関数なので、asyncioを使って結果を待つ必要があります。

github.com

import asyncio
from requests_html import HTMLSession

session = HTMLSession()
r = session.get("https://kiito.hatenablog.com/")
r.html.render(keep_page=True)
loop = asyncio.get_event_loop() 
loop.run_until_complete(r.html.page.screenshot({'path': 'example.png'}))

スクリーンショットの結果

r.html.pageが「pyppeteer.page.Page」のクラスであり、そのメソッドを呼び出せます。

問題点

ただ、現状いくつかの問題点があり、直接pyppeteerのライブラリを操作してクローリングしたほうが良いと判断しました。具体的には以下の3つです。

  • pyppeteerの世界に入ると、急にasync関数になるから難しい
  • ブラウザ自体の操作はそこまでサポートされていない(スクロールダウンしながらページ全体をスクリーンショットしたい)
  • たまに以下のようなエラーが出てしまい、ちゃんと調べていませんが、おそらく「ページを閉じた後にスクリーンショットを撮る」ような挙動になっている
  File "/Users/takeshi/.local/share/virtualenvs/aaa-LzyUpoQe/lib/python3.6/site-packages/pyppeteer/connection.py", line 85, in send
    raise ConnectionError('Connection is closed')
ConnectionError: Connection is closed

参考記事

作者のKenneth Reitzについて

requests_htmlでは他にも、1メソッドでHeadless Chromeインストールから実行までしてくれる下のオシャレなAPIも個人的なお気に入りです。

今まで「(簡単な用途であれば)requestsとBeautifulSoupを使ってクローリングすればいいや」と思っていたのですが、こちらの文言で気になって試してみました。

blog.ikedaosushi.com

pyppeteerの製作者の記事です。

h-miyako.hatenablog.com