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

如何从JavaScript渲染页面中用BeautifulSoup获取图片?

解决JS渲染页面的图片抓取问题

针对你遇到的requests和Selenium都无法获取到图片内容的问题,给出以下两种可行方案:

方案一:优化Selenium等待逻辑,确保页面完全渲染

你之前用Selenium只拿到初始HTML,大概率是因为没有等待JavaScript完成页面渲染。SPA(单页应用)的初始HTML只有空容器,内容全靠后续JS动态加载,所以必须等待元素加载完成后再获取源码。

示例代码:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import base64
import os

# 初始化浏览器驱动(确保ChromeDriver路径正确)
driver = webdriver.Chrome()
target_url = "https://air.ifpshare.com/documentPreview.html?s_id=8ec97e16-51c4-4a77-9f64-7d5dccd9bb41#/detail/561f0184-384c-4ca1-91a4-b2e687865408/record"
driver.get(target_url)

try:
    # 显式等待图片元素出现(根据实际元素调整选择器)
    # 假设图片是带有data:image开头src的img标签
    WebDriverWait(driver, 15).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "img[src^='data:image']"))
    )
except Exception as e:
    print(f"等待图片加载超时: {str(e)}")
    driver.quit()
    exit()

# 获取渲染后的完整页面源码
page_source = driver.page_source
driver.quit()

# 解析页面提取Base64图片并保存
soup = BeautifulSoup(page_source, "html.parser")
img_elements = soup.select("img[src^='data:image']")
div_elements = soup.select("div[style*='data:image']")  # 处理背景图形式的Base64图片

# 创建保存目录
os.makedirs("downloaded_images", exist_ok=True)

# 处理img标签的图片
for idx, img in enumerate(img_elements):
    src = img["src"]
    # 分离Base64编码部分
    img_data = src.split(",")[1]
    # 确定图片格式
    img_format = src.split(";")[0].split("/")[1]
    # 解码并保存
    with open(f"downloaded_images/img_{idx}.{img_format}", "wb") as f:
        f.write(base64.b64decode(img_data))

# 处理div背景图的图片
for idx, div in enumerate(div_elements):
    style = div["style"]
    # 提取Base64部分
    img_data = style.split("url(data:image/")[1].split(";base64,")[1].split(")")[0]
    img_format = style.split("url(data:image/")[1].split(";base64")[0]
    with open(f"downloaded_images/div_bg_{idx}.{img_format}", "wb") as f:
        f.write(base64.b64decode(img_data))

方案二:直接抓取API接口(更高效)

SPA页面的图片数据几乎都是通过后端API获取的,你可以通过Chrome开发者工具抓包找到对应的接口,直接用requests请求接口拿到图片数据,比模拟浏览器更高效。

操作步骤:

  1. 打开Chrome浏览器,访问目标页面,按F12打开开发者工具。
  2. 切换到Network标签,勾选XHR/Fetch过滤选项。
  3. 刷新页面,观察所有请求,找到返回数据包含Base64图片或图片相关字段的接口(通常是带有detail、record等关键词的接口)。
  4. 点击该接口,查看Request URL、Request Method(GET/POST)、Headers(尤其是Cookie、User-Agent、Authorization等)、Request Payload(如果是POST请求)。
  5. 用requests模拟该请求,直接获取图片数据。

示例代码(假设抓包到的API是GET请求):

import requests
import base64
import os

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
    "Cookie": "这里替换成你抓包到的Cookie"
}

# 替换成抓包到的API地址
api_url = "https://air.ifpshare.com/api/document/detail"
params = {
    "s_id": "8ec97e16-51c4-4a77-9f64-7d5dccd9bb41",
    "record_id": "561f0184-384c-4ca1-91a4-b2e687865408"
}

response = requests.get(api_url, headers=headers, params=params)
data = response.json()

# 假设返回的JSON里有images字段,每个元素包含base64数据和格式
os.makedirs("downloaded_images", exist_ok=True)
for idx, img_info in enumerate(data["images"]):
    img_data = img_info["base64"]
    img_format = img_info["format"]
    with open(f"downloaded_images/api_img_{idx}.{img_format}", "wb") as f:
        f.write(base64.b64decode(img_data))

注意事项:

  • 接口请求可能需要携带有效的Cookie或Token,这些信息会随着会话过期,所以要在链接有效期内抓取。
  • 如果接口有签名验证,可能需要分析JS代码生成签名,这种情况优先用方案一。

内容的提问来源于stack exchange,提问作者realreal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 13:36:11