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

Python实现无分页全页截图失败的问题求助

解决网页全页截图失败及拼接断裂问题

我看到你在实现网页全页截图时碰到了两个头疼的问题:第一次尝试只能截取当前可视窗口的内容,第二次手动拼接的方法又会在长页面出现中间断裂的情况。咱们来一步步拆解问题,给出更可靠的解决方案。

先分析你之前的问题

第一次尝试的局限

你第一次的代码里,set_window_size(1920, 1080)只是设置了浏览器窗口的大小,而save_screenshot()和get_screenshot_as_png()默认都只会捕获当前浏览器可视区域的内容,网页超出窗口的部分自然不会被截取到,这就是为什么你只能得到局部截图。

第二次拼接断裂的可能原因

你手动拼接的思路是对的,但出现断裂通常是这几个原因:

  • 滚动后页面的懒加载内容还没完全渲染,你只在开头加了time.sleep(3),但每次滚动后都需要给页面一点加载时间
  • 滚动高度的计算不够准确,document.body.parentNode.scrollHeight有时候会和实际页面高度有偏差
  • 用window.scrollBy()滚动可能因为页面的平滑滚动设置,导致截图时页面还没稳定下来
  • 最后一张图的裁剪逻辑和拼接坐标计算可能存在误差

优化后的全页截图实现

这里给你一个改进后的版本,解决了上述问题,同时更稳定:

import time
import math
import tempfile
import os
from PIL import Image
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

def save_fullpage_screenshot(self):
    # 等待页面完全加载(可以根据页面实际情况调整等待条件)
    WebDriverWait(self.driver, 10).until(
        EC.presence_of_element_located((By.TAG_NAME, "body"))
    )
    time.sleep(1)  # 额外给一点时间让动态内容加载

    # 获取更准确的页面和窗口尺寸
    window_height = self.driver.execute_script('return window.innerHeight')
    # 用更全面的方式获取页面总高度
    scroll_height = self.driver.execute_script('''
        return Math.max(
            document.body.scrollHeight,
            document.body.offsetHeight,
            document.documentElement.clientHeight,
            document.documentElement.scrollHeight,
            document.documentElement.offsetHeight
        );
    ''')
    num_screens = math.ceil(scroll_height / window_height)
    temp_files = []

    try:
        # 逐屏截图
        for i in range(num_screens):
            # 精准滚动到目标位置,关闭平滑滚动避免偏差
            self.driver.execute_script(f'''
                window.scrollTo({{
                    top: {i * window_height},
                    left: 0,
                    behavior: "instant"
                }});
            ''')
            # 等待滚动后的内容加载(可以根据页面情况调整等待时间)
            time.sleep(0.5)
            
            # 创建临时文件保存当前截图
            fd, temp_path = tempfile.mkstemp(prefix=f'ss_{i+1:02}_', suffix='.png')
            os.close(fd)
            temp_files.append(temp_path)
            self.driver.save_screenshot(temp_path)

        # 拼接所有截图
        stitched_image = None
        for idx, temp_path in enumerate(temp_files):
            img = Image.open(temp_path)
            img_width, img_height = img.size

            # 处理最后一张图:如果是最后一页且总页数大于1,裁剪掉多余的空白
            if idx == num_screens - 1 and num_screens > 1:
                actual_section_height = scroll_height - (idx * window_height)
                img = img.crop((0, img_height - actual_section_height, img_width, img_height))
                img_width, img_height = img.size

            # 初始化拼接画布
            if stitched_image is None:
                stitched_image = Image.new('RGB', (img_width, scroll_height))
            
            # 粘贴当前截图到正确位置
            stitched_image.paste(img, (0, idx * window_height))

        # 保存最终全页截图
        stitched_image.save("Y:\\ss\\s.png")
        print("全页截图保存成功!")
    finally:
        # 清理临时文件
        for temp_path in temp_files:
            if os.path.exists(temp_path):
                os.remove(temp_path)

更省心的替代方案:使用Chrome原生全页截图

如果你用的是ChromeDriver,其实不需要自己手动拼接,Chrome提供了原生的全页截图API,代码更简洁且不会出现拼接断裂:

import base64

def save_fullpage_screenshot_chrome(self):
    # 使用Chrome DevTools Protocol直接捕获全页截图
    screenshot_png = self.driver.execute_cdp_cmd(
        "Page.captureScreenshot",
        {"captureBeyondViewport": True, "fromSurface": True}
    )
    # 保存截图
    with open("Y:\\ss\\full_page.png", "wb") as f:
        f.write(base64.b64decode(screenshot_png['data']))

额外建议

  • 对于有大量动态内容(比如图片懒加载、异步渲染)的页面,最好用WebDriverWait等待特定元素加载完成后再截图,而不是固定的time.sleep
  • 如果页面有缩放设置,记得先把浏览器缩放恢复到100%,避免截图尺寸偏差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 13:47:43