使用Nokogiri解析Oddsmath表格无数据返回,请求问题排查
问题分析与解决方案
我帮你排查了这段代码,核心问题出在CSS选择器的冗余和准确性上,另外还有几个小细节可以优化,让我一步步给你拆解:
1. 选择器太冗余,导致匹配失败
你原代码里用了一串类名加ID的组合:
doc.css('table#table-odds-comparison.tbl-odds-comparison.tablesorter.tablesorter-default.hasStickyHeaders')
其实HTML里的ID是唯一的,只用#table-odds-comparison就足够精准定位到目标表格了。多类名组合反而容易出问题——比如页面加载后某些类名可能会被JS动态修改(比如tablesorter-default这类插件生成的类),导致选择器匹配不到任何元素。
2. 优化后的代码
我调整了选择器,同时修复了几个细节问题(比如文本清理、数组操作效率),修改后的代码如下:
def oddsmath require 'nokogiri' require 'open-uri' # 确保引入open-uri库,open方法依赖它 tables_data = [] doc = Nokogiri::HTML(open("http://www.oddsmath.com/odds-comparison/")) # 用ID直接定位唯一表格,at_css返回单个元素(比css更高效) target_table = doc.at_css('#table-odds-comparison') # 提前判断表格是否存在,避免后续代码报错 return tables_data unless target_table # 从第二行开始遍历数据行 target_table.css('tr')[1..-1].each do |tr| # 清理文本中的多余空格和换行 raw_name = tr.at('th').text.strip cell_data = tr.css('td').map { |td| td.text.strip } # 用<<添加数据,比+=更符合Ruby数组操作的最佳实践 tables_data << [raw_name, cell_data] end @output = tables_data end
3. 如果还是拿不到数据?可能是动态加载问题
如果上面的代码还是返回空数组,那大概率是因为这个表格是JS动态渲染的——Nokogiri只能抓取静态HTML,无法执行页面中的JavaScript。这时候你需要用浏览器自动化工具(比如Selenium)来模拟浏览器加载页面,获取渲染后的HTML:
def oddsmath require 'selenium-webdriver' require 'nokogiri' tables_data = [] # 初始化Chrome浏览器驱动(需要提前安装ChromeDriver) driver = Selenium::WebDriver.for :chrome driver.get("http://www.oddsmath.com/odds-comparison/") # 获取浏览器渲染后的页面源码 doc = Nokogiri::HTML(driver.page_source) target_table = doc.at_css('#table-odds-comparison') return tables_data unless target_table target_table.css('tr')[1..-1].each do |tr| raw_name = tr.at('th').text.strip cell_data = tr.css('td').map { |td| td.text.strip } tables_data << [raw_name, cell_data] end # 关闭浏览器 driver.quit @output = tables_data end
调试小技巧
你可以在代码里加一行调试输出,确认是否找到表格:
puts "找到表格数量:#{doc.css('#table-odds-comparison').size}"
如果输出是0,说明选择器确实没匹配到,这时候可以打开目标页面的开发者工具(F12),检查表格的实际ID和结构,确保选择器和页面元素一致。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

