You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Ruby结合Selenium从复杂网页中提取信息?

解决Google Flights动态类名的元素定位方案(Ruby + Selenium)

面对Google Flights这类动态生成类名的网站,不要依赖易变的类名,改用以下更稳定的定位思路:

1. 利用jsname属性定位

Google的页面元素常带有jsname属性,这类属性比动态类名稳定得多,直接通过CSS或XPath定位:

# 定位单个航班容器
flight_container = driver.find_element(:css, 'div[jsname="BXUrOb"]')

# 批量定位所有航班项
all_flights = driver.find_elements(:css, 'div[jsname="BXUrOb"]')

# 定位航班详情子元素
flight_detail = driver.find_element(:css, 'div[jsname="HSrbLb"]')

2. 结合语义化文本/属性定位

通过航班的时间、航空公司、航线等固定文本,配合XPath的层级关系定位:

# 定位包含特定航空公司的航班
delta_flights = driver.find_elements(:xpath, '//div[contains(text(), "Delta")]//ancestor::div[@jsname="BXUrOb"]')

# 定位所有起飞时间元素
departure_times = driver.find_elements(:xpath, '//div[@jsname="BXUrOb"]//span[contains(@aria-label, "Departure")]')

3. 相对定位(Selenium 4+支持)

先定位稳定的父容器,再在容器内查找子元素,缩小定位范围:

# 找到航班列表的根容器(假设该容器属性稳定)
flight_list_root = driver.find_element(:css, 'div[role="list"]')

# 在根容器内批量获取航班项
flights_in_list = flight_list_root.find_elements(:css, 'div[jsname="BXUrOb"]')

4. 借助Capybara的高级选择器

既然已引入Capybara,可以用它更简洁的语法结合层级和文本定位:

# 绑定已有Selenium driver到Capybara
Capybara.current_driver = :selenium_chrome
Capybara.page.driver = driver

# 批量获取所有航班
all_flights = Capybara.page.all('div[jsname="BXUrOb"]')

# 定位包含指定航线的航班
target_flight = Capybara.page.find('div', text: 'SFO → LAX').ancestor('div[jsname="BXUrOb"]')

关键注意事项

  • 等待元素加载:动态页面需用显式等待避免定位失败:
    wait = Selenium::WebDriver::Wait.new(timeout: 10)
    flights = wait.until { driver.find_elements(:css, 'div[jsname="BXUrOb"]').any? }
    
  • 反爬规避:Google Flights有反爬机制,操作间适当添加延迟,避免频繁请求
  • 属性稳定性验证:jsname虽比类名稳定,但版本迭代可能微调,需定期验证定位表达式

内容的提问来源于stack exchange,提问作者Grant Sayer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 12:53:17