Webページの中に取得したいデータがあるのに、ページソースのHTMLファイルをダウンロードして中身を見ても見つからない…」そんな状況、技術者なら一度は遭遇しているはずです。
- HTMLファイルを保存しても、欲しかったテーブルやリストが含まれていない
- 自動処理でHTMLを取得したのに、構造化されたデータが見つからない
最近のWebページは動的なもの、つまりJavaScriptによって後からHTMLを生成する構造のものが少なくありません。そのようなWebページの場合、URLを開いた瞬間に取得できるHTMLは「プレースホルダー」にすぎず、本当に欲しいHTMLはJavaScriptが走った後に初めて現れるのです。つまり、そのようなWebページのHTMLファイルをダウンロードしても「プレースホルダー」を手にしたに過ぎないのです。そこでこの記事では、requests-htmlライブラリを使って、JavaScriptでレンダリングされた後のHTMLコンテンツ、つまり本当に欲しいHTMLコンテンツをプログラム上で取得するための方法を紹介します。
必要なライブラリのインストール
動的なWebページのHTMLコンテンツを取得するためには、requests-html
というライブラリが使えます。また、わたしが requests-html
を使った時には lxml_html_clean
も必要でした。それらをpipコマンドでインストールできます。
pip install requests-html lxml_html_clean
動的HTML取得関数の実装
requests-htmlを使用してget_rendered_html関数を実装してみました。
from requests_html import HTMLSession
async def get_rendered_html(url):
session = HTMLSession()
r = session.get(url)
r.html.render(timeout=60)
session.close()
return r.html.html
この関数get_rendered_htmlは、同期的にWebページを取得し、JavaScriptをレンダリングした後のHTMLを返します。レンダリングに時間がかかることを踏まえ、タイムアウトを60秒としています。
💡補足:requests-htmlには非同期処理版のAsyncHTMLSessionもあります。
from requests_html import AsyncHTMLSession
async def get_rendered_html(url):
session = AsyncHTMLSession()
r = await session.get(url)
await r.html.arender(timeout=60)
await session.close()
return r.html.html
- 非同期処理とは、プログラムがタスクを実行する際に、タスクの完了を待たずに次のタスクに進むことができる処理方式です。時間のかかる処理(ネットワーク通信や IO)を待っている間に、他の処理を並行して進める、というような使い方をします。
- 今回は簡単のため同期処理でプログラムを書いていますが、Jupyter Notebook 上で実行する場合は
AsyncHTMLSessionを使う必要があるようです。
実行例
では、get_rendered_html関数を実際に実行してみましょう。
url = https://vuejs.org/examples/#hello-world
def main():
text = get_rendered_html(url)
print(text)
if __name__ == '__main__':
main()
urlに https://vuejs.org/examples/#hello-world を指定してみると、上のプログラムはレンダリングされたHTMLコンテンツを正常に取得して出力します。試しに同じ
URL を curl 等で取得して比較すると、違いがわかると思います。
この方法を使えば、動的に生成されたHTMLもPythonで扱えるようになります。

