如何使用Watir、geckodriver与Firefox截取全页面截图?
嘿,我之前升级Watir和Firefox后也碰到过这个糟心的问题——默认截图只截视口,geckodriver的全页API又遥遥无期。不过折腾了一阵,找到了两个不用回滚环境的办法,分享给你:
方案一:滚动分段截图+拼接(最可靠)
这个方法的核心思路是模拟人工滚动页面,每次截取当前视口的截图,最后用图片处理工具把所有截图垂直拼接起来。刚好你已经在用MiniMagick,完美适配这个方案。
具体代码实现如下:
require 'watir' require 'mini_magick' require 'base64' def full_page_screenshot(browser) # 获取页面基础参数(适配Retina屏的分辨率加倍) viewport_height = browser.execute_script("return window.innerHeight") total_height = browser.execute_script("return document.documentElement.scrollHeight") # 计算Retina屏幕的缩放系数 scale_factor = browser.screenshot.base64.size / (browser.execute_script("return window.innerWidth * window.innerHeight * 4").to_f) screenshots = [] current_y = 0 while current_y < total_height # 滚动到当前目标位置 browser.execute_script("window.scrollTo(0, #{current_y});") # 等待页面滚动后加载稳定(可根据页面加载速度调整时长) sleep 0.5 # 截取当前视口的截图并保存 blob = Base64.decode64(browser.screenshot.base64) screenshots << MiniMagick::Image.read(blob) # 计算下一次滚动的位置,避免重复截取顶部内容 current_y += viewport_height end # 创建空白的拼接画布 combined_image = MiniMagick::Image.new(screenshots[0].width, (total_height * scale_factor).to_i) do |img| img.background 'white' end current_y_offset = 0 screenshots.each_with_index do |img, index| # 最后一张截图可能不需要截满视口,自动裁剪到剩余页面高度 img_height = if index == screenshots.length - 1 ((total_height - (current_y_offset / scale_factor)) * scale_factor).to_i else img.height end # 将当前截图拼接到画布上 combined_image = combined_image.composite(img) do |c| c.compose 'over' c.geometry "+0+#{current_y_offset}" c.crop "0x#{img_height}+0+0" end current_y_offset += img_height end combined_image end # 使用示例 b = Watir::Browser.new :firefox b.goto "https://daringfireball.net" full_image = full_page_screenshot(b) full_image.write "full_page.png" b.quit
注意事项:
- 加入了
sleep等待页面滚动稳定,避免出现空白或加载不全的截图,你可以根据页面实际加载速度调整时长。 - 自动适配了Retina屏的分辨率缩放问题,确保拼接后的图片高度和实际页面一致。
- 最后一张截图会自动裁剪到剩余页面高度,避免出现多余空白。
方案二:临时调整浏览器窗口高度(简单但有局限)
如果你的页面高度不是特别夸张(没有超过浏览器允许的最大窗口高度),可以直接把浏览器窗口的高度设置为页面的总滚动高度,此时视口就等于整个页面,直接截图即可。
代码示例:
require 'watir' require 'mini_magick' require 'base64' b = Watir::Browser.new :firefox b.goto "https://daringfireball.net" # 获取页面总高度和当前窗口宽度 page_height = b.execute_script("return document.documentElement.scrollHeight") current_width = b.driver.manage.window.size.width # 调整窗口高度为页面总高度(部分系统/浏览器对窗口高度有上限) b.driver.manage.window.resize_to(current_width, page_height) # 等待窗口调整完成 sleep 0.5 # 此时截图就是全页面内容 blob = Base64.decode64(b.screenshot.base64) image = MiniMagick::Image.read(blob) image.write "full_page_simple.png" b.quit
局限性:
- 很多浏览器(比如macOS上的Firefox)对窗口高度有上限,不能超过屏幕最大高度,超长页面会失效。
- 部分页面的元素布局依赖窗口大小,调整窗口高度可能导致页面布局变形,影响截图效果。
两个方案里,我个人更推荐第一个,虽然代码多一点,但兼容性和可靠性都更高,不管页面多长都能搞定。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

