screenshot()截不满整页,因其仅捕获当前视口内容,不触发滚动或合成,对超长页面(如>10000px)仅得顶部一屏、底部全黑;须手动滚动+分段截图+PIL拼接,并等待JS动态内容就绪才能实现完整DOM渲染快照。

长截屏不能只靠 screenshot(),必须滚动+拼接;网页快照若需完整 DOM 渲染(含懒加载、JS 交互后状态),得等元素就绪再截。
为什么 screenshot() 截不满整页?
ChromeDriver 默认只截当前视口(viewport)内容,即使页面有滚动条,screenshot() 也不会自动滚到底部再拼——它压根不滚动。遇到高度超 10000px 的管理后台或文档页,直接截出白底+顶部内容,底部全黑或空白。
- 真实表现:调用
driver.get("https://example.com"); driver.save_screenshot("a.png")后打开图片,发现只有一屏 - 根本原因:底层是 DevTools Protocol 的
Screenshot.captureScreenshot,不带滚动逻辑 - 兼容性注意:Firefox 的
get_full_page_screenshot_as_png()声称支持全页,但实际对 position: fixed 元素、iframe 内容、阴影/滤镜渲染常失效
手动滚动拼接长图的可靠做法
核心思路是分段滚动 → 截图 → 计算偏移 → 合成 PNG。别依赖第三方库(如 pyautogui 或过时的 selenium-screenshot),自己控制更稳。
- 先用
driver.execute_script("return document.body.scrollHeight")获取总高度 - 用
driver.execute_script("window.scrollTo(0, arguments[0])", y)精确滚动到目标 Y 坐标(避免scrollIntoView被 sticky header 干扰) - 每次滚动后
time.sleep(0.3)等渲染(尤其含动画/图表的页面),必要时加WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.TAG_NAME, "footer"))) - 截图存为
PIL.Image对象,用Image.new("RGB", (width, total_height))创建画布,逐张paste(),Y 偏移 = 当前滚动位置
示例关键片段:
立即学习“Python免费学习笔记(深入)”;
height = driver.execute_script("return document.body.scrollHeight")
width = driver.execute_script("return window.innerWidth")
chunks = []
for y in range(0, height, 1080): # 每次滚 1080px(常见屏高)
driver.execute_script(f"window.scrollTo(0, {y})")
time.sleep(0.3)
chunks.append(Image.open(io.BytesIO(driver.get_screenshot_as_png())))
# 合成逻辑略(需对齐 width,处理最后一块裁剪)
网页快照要「所见即所得」,必须等 JS 动态内容就绪
所谓“快照”不是静态 HTML 抓取,而是浏览器渲染完成后的像素快照。如果页面用 React/Vue 加载表格、用 IntersectionObserver 触发图片懒加载,get_screenshot_as_png() 可能截到空容器或占位图。
- 不要只等
document.readyState == "complete",它不保证 Vuemounted或 ReactuseEffect执行完 - 优先等关键元素出现:
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "data-table"))) - 对图表类页面(ECharts / Chart.js),加一句
driver.execute_script("return typeof echarts !== 'undefined' && echarts.getInstanceById('chart')?.isFinished()") - 极端情况可兜底:
driver.execute_script("return performance.getEntriesByType('navigation')[0].loadEventEnd > 0")确保 load 事件已触发
导出 PNG 时容易被忽略的坑
合成后的长图若发虚、错位、颜色异常,大概率栽在这几个点上:
- Chrome 启动参数没关缩放:
--force-device-scale-factor=1必须加,否则 HiDPI 屏幕下截图模糊 - 窗口尺寸未固定:
driver.set_window_size(1920, 1080)在滚动前执行,避免每次滚动窗口自适应导致宽度变化 - PIL 合成时没统一模式:
chunk.convert("RGB")强制转三通道,否则透明 PNG 和背景色混合出灰边 - Linux 服务器无头运行时缺字体:安装
fonts-liberation和xvfb,否则中文显示方块,影响快照可用性
合成代码里漏掉 driver.execute_script("window.scrollTo(0, 0)") 回顶,最后一张截图可能偏移,导致拼图错行——这个细节调试时最难排查。


















