やりたいこと
User-Agentによってスマホ用とPC用のページが切り替わるWebページで、スマホ用ページのスクリーンショットを撮りたいです。
どのようにすればスマホで表示している画面と同様の画面がスクリーンショットできるか教えて頂きたいです。
状況
screenshot()
で、ターゲットWebページのスクリーンショットを画像ファイルとして保存することはできました。
しかし保存された画像は、実際にスマホで表示した画面とは異なるものでした。
表示が異なる箇所の例
- 本来設定されている背景色が設定がない(白背景)
- トップ画像などすべての画像が表示されていない
- ハンバーガーメニューに畳まれるはずのメニューが
<ul><li>
をそのままリスト表示した状態で表示されている
これらのことから恐らくそもそもCSSが適用されていない状態と思われます。
実施したスマホ用ページはブラウザサイズをどれだけ大きくしても、表示横幅が広がっていくだけでコンテンツの表示に変更はないページです。
そのためサイズによる表示の違いは関係ありません。
またPCのChromeからUser-Agent偽装してアクセスし、正常に表示されることを確認したUser-Agentを用いて実施しても、同様の状況となっております。
試したこと
arender()のkeep_page, reloadパラメータに応じた保存画像の状況
・r.html.arender()
のkeep_page
, reload
の値を変更することで状況が変わった。
- keep_page=False: r.html.page=Noneとなり
r.html.page.screenshot()
でエラー(このためTrueに固定) - reload=True: r.html.arender()が実行された後、PC用サイトが読み込まれるため、PC用ページが保存される
- reload=False: r.html.arender()が実行された後、スマホ用サイトが読み込まれるが、スマホ用ページだが画像やスタイルなど適用されていないようなものが保存される(表示画面とは異なる状態)
→例えば背景が黒なのに白い、ハンバーガーメニューで畳まれているメニューがリスト表示されている等
arender()のwait, sleepパラメータを設定
arender()にwait, sleepパラメータを設定(長めにしてみた)。
結果は変わらず期待した画像の取得はできなかった。
python
1await r.html.arender(wait=60, sleep=60, keep_page=True, reload=False)
r.html.page.screenshot.__doc__を確認
print(r.html.page.screenshot.doc)を出力してみたが、画像ファイル形式に関するものしかなかったため、今回の期待値へのアプローチとは関係ない模様。
# print(r.html.page.screenshot.__doc__) Take a screen shot. The following options are available: * ``path`` (str): The file path to save the image to. The screenshot type will be inferred from the file extension. * ``type`` (str): Specify screenshot type, can be either ``jpeg`` or ``png``. Defaults to ``png``. * ``quality`` (int): The quality of the image, between 0-100. Not applicable to ``png`` image. * ``fullPage`` (bool): When true, take a screenshot of the full scrollable page. Defaults to ``False``. * ``clip`` (dict): An object which specifies clipping region of the page. This option should have the following fields: * ``x`` (int): x-coordinate of top-left corner of clip area. * ``y`` (int): y-coordinate of top-left corner of clip area. * ``width`` (int): width of clipping area. * ``height`` (int): height of clipping area. * ``omitBackground`` (bool): Hide default white background and allow capturing screenshot with transparency. * ``encoding`` (str): The encoding of the image, can be either ``'base64'`` or ``'binary'``. Defaults to ``'binary'``.
ソース
参考ページを元にスクリーンショット用のメソッドを作成しました。
python
1import requests_html 2from requests_html import AsyncHTMLSession 3 4def screenshot(asession, url, headers, is_full_page): 5 async def process(): 6 asession.headers = headers 7 print(f'- url: {url}\n- headers: {headers}\n') 8 r = await asession.get(url, headers=headers, verify=False) 9 await r.html.arender(keep_page=True, reload=False) 10 await r.html.page.screenshot({'path': 'screenshot.png', 'fullPage': is_full_page}) 11 return r 12 r = asession.run(process)[0] 13 14 15assesion = AsyncHTMLSession() 16url = 'https://exsample.com/' 17headers = { 18 "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) > > AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", 19} 20is_full_page = True 21screenshot(assesion, url, headers, is_full_page)
参考ページ
回答1件
あなたの回答
tips
プレビュー