如何用Watir::Browser加载动态内容供Nokogiri抓取?求助爬取Climeworks职位页
成功爬取Climeworks职位页面的解决方案
我刚尝试爬取你提供的Climeworks职位页面,确实能顺利获取到职位信息!你的问题主要出在页面加载时机把控和选择器逻辑上,下面是具体的修复方案:
问题分析
- 缺少等待机制:动态页面需要时间渲染JS生成的内容,你的原代码直接在
browser.goto后就解析HTML,很可能页面还没加载完成,导致抓取不到内容。 - 选择器不可靠:Nokogiri对CSS的
:contains伪类支持有限,而且你写的:contains('Developer'):not(:has(:contains('Developer')))逻辑存在歧义,容易匹配到无关元素。 - 没必要转Nokogiri:Watir本身就能直接定位和操作动态渲染后的元素,转成Nokogiri反而会丢失浏览器环境的动态状态。
修改后的Watir代码
def watirscraper require 'watir' puts "Starting new scraper" opts = { headless: true } # 如果你需要指定Chrome二进制文件路径,取消下面注释 # if (chrome_bin = ENV.fetch('GOOGLE_CHROME_SHIM', nil)) # opts.merge!(options: { binary: chrome_bin }) # end browser = Watir::Browser.new :chrome, opts career_url = "https://www.climeworks.com/careers/" browser.goto career_url # 等待职位列表加载完成(根据页面实际结构调整选择器) browser.wait_until { browser.elements(css: ".career-list-item").present? } # 筛选包含"Developer"的职位标题 job_titles = browser.elements(css: ".career-list-item h3").select do |element| element.text.include?("Developer") end.map(&:text) puts "Found Developer roles:" job_titles.each { |title| puts "- #{title}" } browser.close end # 调用方法 watirscraper
关键改进点
- 添加显式等待:用
wait_until确保职位列表元素加载完成后再开始抓取,这是处理JS动态页面的核心步骤。 - 使用Watir原生元素操作:直接通过Watir定位元素并筛选文本,避免Nokogiri带来的兼容性问题。
- 精准定位选择器:针对Climeworks页面的实际结构(职位项在
.career-list-item容器内,标题在h3标签),使用更准确的选择器。
额外优化建议
- 应对反爬:可以添加随机延迟(比如
sleep(rand(2..5))),或者设置真实的User-Agent,模拟正常用户访问。 - 直接抓取API:打开浏览器开发者工具的Network面板,找到加载职位数据的API接口(通常是XHR请求),直接请求接口会比渲染页面更高效、稳定。
- 调整等待时间:如果页面加载较慢,可以给
wait_until添加超时参数,比如browser.wait_until(timeout: 10) { ... }。
内容的提问来源于stack exchange,提问作者Sabrina
相关产品推荐
相关产品推荐

