概要
PlaywrightのPageから正確な画像ファイルを抽出する
問題
Playwrightでテスト対象のページが生成した画像をファイルとして取得するAPIは2022/12現在存在しない
そのため Page
の evaluate
を活用して上手く取り出してやる必要がある
解決
第一候補に挙がるのは、Canvas + toDataURL
だが、画像をサブドメインのCDNなどに乗せているとOriginの問題が発生する
加えて、jpegの場合はcanvasを通すと完全に同一の画像にはならない
そこで、evaluate
で画像をBlobからbase64に変換するコードを実行し、結果のbase64 encoded string を外に取り出して、Python側でdecodeする
実際のコード
Server
echo '<html><head></head><body><img src="https://playwright.dev/img/logos/Browsers.png"></body></html>' > target.html
python3 -m http.server
Playwright
import base64
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
for browser_type in [p.chromium]:
browser = browser_type.launch()
page = browser.new_page()
page.goto('localhost:8000')
image_locator = page.locator("img[src*='$target_condition']").nth(0)
image_src = orig_image_locator.get_attribute("src")
page.goto(image_src)
image_b64 = page.evaluate("async () => {return await fetch(window.location.href).then( response => response.blob() ).then( blob => new Promise( callback => {let reader = new FileReader(); reader.onload = function(){ callback(this.result) } ; reader.readAsDataURL(blob) }))}")
with open('extracted.png', 'wb') as f:
# jpg: .replace("data:image/jpeg;base64,", "").
image_b64 = image_b64.replace("data:image/png;base64,", "")
f.write(base64.b64decode(image_b64))