You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否不用额外发起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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 09:36:02