playwright 直接拦截获取图片数据
背景
playwright 控制浏览器后,获取其中的图片还需要手动获取 src 重新下载,是不是有点浪费时间?甚至有的网站图片下载时还需要加代理,无法百分百成功,但是浏览器加载下载的时候却是一直都可以的。
这时候就需要利用起来 playwright 的网络拦截功能了!
实现
1. 拦截功能实现
主要思路就是过滤出需要的响应,然后对特征符号进行哈希,以此命名文件保存下来,以供备用。
def handle_route(response) -> None:
"""
直接拦截获取浏览器下载的图片,写到硬盘中
"""
# 过滤掉不需要的响应
if not 'xxxxx.com' in response.request.url:
return
# logger.info(f"请求:{response.request.url}")
body = response.body()
# 获取图片文件名的hash(get_md5 方法自行实现,几行)
file_hash = get_md5(os.path.basename(response.request.url))
check_path = f"./img/{file_hash}.jpg"
# 还可以对图片进行预处理等等 -ercilan
#image = np.asarray(bytearray(body), dtype="uint8")
#image = cv2.imdecode(image, cv2.IMREAD_COLOR)
#image = cv2.resize(image, dsize=size)
#cv2.imwrite(check_path, image)
with open(check_path, mode="wb") as f:
f.write(body)
logger.info(f"图片拦截保存完毕:{file_hash}")
2. 设置监听
在对应 page 设置上:
page.on("response", handle_route)
3. 获取图片
在这里有一个问题,浏览器下载图片与我们的程序是并行的,因此就是需要确保浏览器已经加载完图片,然后我们的程序才能继续运行。
# 获取到目标图片src(顺便利用playwright等待img渲染上)
pic_src = page.get_attribute('//img[@id="xxx-image"]', 'src', timeout=10000)
logger.debug(pic_src)
# 等待图片加载/下载完成
while True:
page.wait_for_timeout(1000)
img_status = page.evaluate('''() => {
return document.getElementById("xxx-image").complete;
}''')
logger.debug(f"图片状态:{img_status}")
if img_status:
break
logger.info("图片加载完成")
# 获取其图片名hash,检查是否已经下载了,下载了就可以直接使用了,不必再次下载
check_path = f"./img/{get_md5(os.path.basename(pic_src))}.jpg"
if os.path.exists(check_path):
logger.debug(f"图片已下载过,跳过下载")
# ...