Selenium 截取完整长页面:滚动拼接与 CDP 两种做法
默认 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。
- 截图前先等关键节点渲染完成,避免白屏或懒加载空洞。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 HT Notes