默认 driver.save_screenshot() 只截当前视口。要保存整页长图,可以用滚动拼接,或走 CDP。

方案一:滚动拼接

import time
from io import BytesIO
from PIL import Image

def take_full_screenshot_scroll(driver, filename):
    driver.maximize_window()
    time.sleep(0.5)
    total_height = driver.execute_script("return document.body.scrollHeight")
    viewport_height = driver.execute_script("return window.innerHeight")
    width = driver.execute_script(
        "return Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);"
    )
    driver.set_window_size(width, viewport_height)
    slices, offset = [], 0
    while offset < total_height:
        driver.execute_script(f"window.scrollTo(0, {offset});")
        time.sleep(0.2)
        slices.append(Image.open(BytesIO(driver.get_screenshot_as_png())))
        offset += viewport_height
    image = Image.new("RGB", (slices[0].width, total_height))
    y = 0
    for im in slices:
        image.paste(im, (0, y))
        y += viewport_height
    image.crop((0, 0, slices[0].width, total_height)).save(filename)

方案二:CDP(推荐 Chromium)

import base64

def take_full_screenshot_cdp(driver, filename):
    metrics = driver.execute_cdp_cmd("Page.getLayoutMetrics", {})
    width = int(metrics["contentSize"]["width"])
    height = int(metrics["contentSize"]["height"])
    driver.execute_cdp_cmd("Emulation.setDeviceMetricsOverride", {
        "mobile": False, "width": width, "height": height, "deviceScaleFactor": 1,
        "screenOrientation": {"type": "portraitPrimary", "angle": 0},
    })
    result = driver.execute_cdp_cmd("Page.captureScreenshot", {
        "format": "png", "fromSurface": True, "captureBeyondViewport": True,
    })
    open(filename, "wb").write(base64.b64decode(result["data"]))
    driver.execute_cdp_cmd("Emulation.clearDeviceMetricsOverride", {})

选择建议

  • 页面不长、兼容性优先:滚动拼接。
  • Chrome/Edge 且要清晰整页:CDP。
  • 截图前先等关键节点渲染完成,避免白屏或懒加载空洞。