能否不用额外发起URL请求直接从Selenium中下载已加载的图片?
有多种成熟的实现方案,核心逻辑是直接读取浏览器已加载缓存的资源,无需二次发起HTTP请求,以下是具体实现方式:
方案1:JS Canvas转Base64(全版本Selenium通用,无额外依赖)
原理是通过Selenium调用浏览器侧JS代码,将已加载完成的图片绘制到Canvas元素,导出为Base64字符串后在本地解码保存,全程无额外网络请求:
from selenium import webdriver import base64 driver = webdriver.Chrome() driver.get("你的目标网页地址") # 获取页面内所有图片元素 imgs = driver.find_elements("tag name", "img") for idx, img in enumerate(imgs): # 执行JS转换图片为Base64 base64_raw = driver.execute_script(""" const targetImg = arguments[0]; const canvas = document.createElement('canvas'); // 使用图片原始尺寸绘制避免模糊 canvas.width = targetImg.naturalWidth; canvas.height = targetImg.naturalHeight; const ctx = canvas.getContext('2d'); ctx.drawImage(targetImg, 0, 0); // 可替换为image/jpeg,第二个参数控制导出质量0-1 return canvas.toDataURL('image/png').split(',')[1]; """, img) # 解码保存到本地 img_bytes = base64.b64decode(base64_raw) with open(f"img_{idx}.png", "wb") as f: f.write(img_bytes) driver.quit()
注意事项:
- 默认仅支持同域图片,跨域图片会触发CORS限制,可在Chrome启动时添加参数
options.add_argument("--disable-web-security")关闭跨域限制即可 - 若图片设置了跨域属性,可在JS中新增
targetImg.crossOrigin = 'anonymous'处理
方案2:CDP网络响应拦截(Selenium4+ 适用,批量操作效率最高)
利用Chrome DevTools Protocol直接监听浏览器所有网络响应,匹配到图片资源时直接读取已加载完成的响应体,是零额外请求、性能最高的方案,适合大规模批量采集场景:
from selenium import webdriver import base64 # 配置浏览器启动参数 options = webdriver.ChromeOptions() driver = webdriver.Chrome(options=options) # 开启Network域监听 driver.execute_cdp_cmd("Network.enable", {}) # 注册响应监听回调 def save_image_response(event): resp_info = event["response"] # 匹配图片类型的响应 if "image" in resp_info["mimeType"]: req_id = event["requestId"] # 直接获取已加载的响应内容 resp_body = driver.execute_cdp_cmd("Network.getResponseBody", {"requestId": req_id}) # 生成文件名,可自定义规则 file_suffix = resp_info["mimeType"].split("/")[1] file_name = f"{hash(resp_info['url'])}.{file_suffix}" # 处理二进制内容 if resp_body["base64Encoded"]: img_bytes = base64.b64decode(resp_body["body"]) else: img_bytes = resp_body["body"].encode() with open(file_name, "wb") as f: f.write(img_bytes) # 绑定响应接收事件 driver.add_cdp_listener("Network.responseReceived", save_image_response) # 访问网页,所有加载的图片会自动被拦截保存 driver.get("你的目标网页地址") driver.quit()
方案3:替换为Playwright(可选,开发成本更低)
如果不限制使用Selenium,Playwright对浏览器资源拦截的封装更成熟,代码更简洁,性能也优于原生Selenium:
from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() # 注册响应监听 def handle_response(resp): content_type = resp.header_value("content-type") if content_type and "image" in content_type: img_bytes = resp.body() # 自定义文件名规则 file_name = resp.url.split("/")[-1].split("?")[0] if not file_name: file_name = f"{hash(resp.url)}.{content_type.split('/')[1]}" with open(file_name, "wb") as f: f.write(img_bytes) page.on("response", handle_response) page.goto("你的目标网页地址") browser.close()
内容的提问来源于stack exchange,提问作者saml
相关产品推荐
相关产品推荐

