Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 用Nokogiri抓取一个网站_Ruby_Ruby On Rails 3_Css Selectors_Nokogiri_Web Scraping - Fatal编程技术网

Ruby 用Nokogiri抓取一个网站

Ruby 用Nokogiri抓取一个网站,ruby,ruby-on-rails-3,css-selectors,nokogiri,web-scraping,Ruby,Ruby On Rails 3,Css Selectors,Nokogiri,Web Scraping,我用Nokogiri来刮一个网站,当我试图从表中抓取一个字段时遇到了一个问题。我正在使用查找表的CSS选择器。我正在从一个数据库中获取数据 我使用的方法如下所示: def scrape_database url = "http://safer.fmcsa.dot.gov/query.asp?searchtype=ANY&query_type=queryCarrierSnapshot&query_param=USDOT&query_string=#{self.dot}#

我用Nokogiri来刮一个网站,当我试图从表中抓取一个字段时遇到了一个问题。我正在使用查找表的CSS选择器。我正在从一个数据库中获取数据

我使用的方法如下所示:

def scrape_database
  url = "http://safer.fmcsa.dot.gov/query.asp?searchtype=ANY&query_type=queryCarrierSnapshot&query_param=USDOT&query_string=#{self.dot}#Inspections"
  doc = Nokogiri::HTML(open(url))
  self.name = doc.at_css("tr:nth-child(4) .queryfield").text
  self.address = doc.at_css("tr:nth-child(6) .queryfield").text
end
我使用该语法抓取上表中的所有字段,该方法运行良好,但它下面的崩溃率/检查表存在问题

以下是我用来获取这些信息的方法:

self.vehicle_inspections = doc.at_css("center:nth-child(13) tr:nth-child(2) :nth-child(2)").text

undefined method `text' for nil:NilClass
如果我从末尾删除文本,该方法将运行,但显然不会获取任何相关信息。我假设这是由于我用来抓取字段的复杂选择器造成的,但我不太确定


有人遇到过类似的问题吗?你能给我一些建议吗?

是的,这个错误意味着你的CSS选择器找不到信息;at_css返回nil,且nil.text无效。你可以像这样防范它:

insp = doc.at_css("long example css selector")
self.vehicle_inspections = insp && insp.text
然而,我觉得你需要这些数据。由于您既没有提供HTML页面,也没有提供CSS选择器,因此我无法帮助您创建一个工作正常的CSS或XPath选择器

对于将来的问题,或者对这个问题的编辑,请注意,与挥手和松散地描述代码的外观相比,更倾向于实际精简的代码。如果您向我们显示HTML页面或相关代码段,并描述您想要的元素/文本/属性,我们可以告诉您如何选择它

我在那页上看到六张桌子。哪个是碰撞率/检查表?鉴于您的URL末尾包含了检查,我假设您所说的是美国检查/崩溃部分下面的两个表。以下是匹配每个选项的XPath选择器:

require 'nokogiri'
require 'open-uri'

url = "http://safer.fmcsa.dot.gov/query.asp?searchtype=ANY&query_type=queryCarrierSnapshot&query_param=USDOT&query_string=800585"
doc = Nokogiri::HTML(open(url))
table1 = doc.at_xpath('//table[@summary="Inspections"][preceding::h4[.//a[@name="Inspections"]]]')
table2 = doc.at_xpath('//table[@summary="Crashes"][preceding::h4[.//a[@name="Inspections"]]]')

# Find a row by index (1 is the first row)
vehicle_inspections    = table1.at_xpath('.//tr[2]/td').text.to_i

# Find a row by header text
out_of_service_drivers = table1.at_xpath('.//tr[th="Out of Service"]/td[2]').text.to_i

p [ vehicle_inspections, out_of_service_drivers ]
#=> [6, 0]

tow_crashes = table2.at_xpath('.//tr[th="Crashes"]/td[3]').text.to_i
p tow_crashes
#=> 0
XPath查询可能看起来很吓人。让我解释一下它们是如何工作的:

//表[@summary=Inspections][previous::h4[.//a[@name=Inspections]]

//在文档的任何级别查找表 [@summary=Inspections]…但仅当它具有具有此值的summary属性时 [前面的::h4…]…并且仅当您可以在文档的前面找到元素时 [.//a…]…具体地说,a下面有一个 [@name=Inspections]…并且该文本必须具有name属性。 这实际上会匹配两个表页面后面还有一个summary=Inspections表,但是使用at_xpath会找到第一个匹配表

.//tr[2]/td

. 从该表的当前节点开始 //tr[2]…找到第二个在任何级别上都是后代的对象 /td…然后找到那个孩子。 同样,因为我们使用的是at_xpath,所以我们找到了第一个匹配项

.//tr[th=停止服务]/td[2]

. 从该表的当前节点开始 //tr…查找任何级别的后代 [th=停止服务]…但只有那些有此文本的子对象 /td[2]…然后找到这些的第二个孩子。 在本例中,只有一个符合条件,因此只有一个符合条件,但我们仍然使用at_xpath,以便直接获取该节点,而不是包含单个元素的节点集

这里和任何屏幕抓取的目标都是锁定页面上有意义的值,而不是任意索引

例如,我可以将table1 xpath编写为:

# Find the first table with this summary
table1 = doc.at_xpath('//table[@summary="Inspections"][1]')
……甚至

# Find the 20th table on the page
//table[20]
然而,这些都是脆弱的。如果有人向页面中添加新的节,或者添加或删除格式表的代码,则会导致这些表达式中断。您希望搜索可能不会更改的强属性和文本,并在此基础上锚定搜索


车辆同样脆弱,依赖于行的顺序而不是行的标签文本。

是的,该错误意味着您的CSS选择器找不到信息;at_css返回nil,且nil.text无效。你可以像这样防范它:

insp = doc.at_css("long example css selector")
self.vehicle_inspections = insp && insp.text
然而,我觉得你需要这些数据。由于您既没有提供HTML页面,也没有提供CSS选择器,因此我无法帮助您创建一个工作正常的CSS或XPath选择器

对于将来的问题,或者对这个问题的编辑,请注意,与挥手和松散地描述代码的外观相比,更倾向于实际精简的代码。如果您向我们显示HTML页面或相关代码段,并描述您想要的元素/文本/属性,我们可以告诉您如何选择它

我在那页上看到六张桌子。哪个是碰撞率/检查表?鉴于您的URL末尾包含了检查,我假设您所说的是美国检查/崩溃部分下面的两个表。以下是匹配每个选项的XPath选择器:

require 'nokogiri'
require 'open-uri'

url = "http://safer.fmcsa.dot.gov/query.asp?searchtype=ANY&query_type=queryCarrierSnapshot&query_param=USDOT&query_string=800585"
doc = Nokogiri::HTML(open(url))
table1 = doc.at_xpath('//table[@summary="Inspections"][preceding::h4[.//a[@name="Inspections"]]]')
table2 = doc.at_xpath('//table[@summary="Crashes"][preceding::h4[.//a[@name="Inspections"]]]')

# Find a row by index (1 is the first row)
vehicle_inspections    = table1.at_xpath('.//tr[2]/td').text.to_i

# Find a row by header text
out_of_service_drivers = table1.at_xpath('.//tr[th="Out of Service"]/td[2]').text.to_i

p [ vehicle_inspections, out_of_service_drivers ]
#=> [6, 0]

tow_crashes = table2.at_xpath('.//tr[th="Crashes"]/td[3]').text.to_i
p tow_crashes
#=> 0
XPath查询可能看起来很吓人。让我解释一下它们是如何工作的:

//表[@summary=Inspections][previous::h4[.//a[@name=Inspections]]

//在文档的任何级别查找表 [@summary=Inspections]…但仅当它具有具有此值的summary属性时 [预 ceding::h4…]…并且仅当您可以在文档的前面找到元素时 [.//a…]…具体地说,a下面有一个 [@name=Inspections]…并且该文本必须具有name属性。 这实际上会匹配两个表页面后面还有一个summary=Inspections表,但是使用at_xpath会找到第一个匹配表

.//tr[2]/td

. 从该表的当前节点开始 //tr[2]…找到第二个在任何级别上都是后代的对象 /td…然后找到那个孩子。 同样,因为我们使用的是at_xpath,所以我们找到了第一个匹配项

.//tr[th=停止服务]/td[2]

. 从该表的当前节点开始 //tr…查找任何级别的后代 [th=停止服务]…但只有那些有此文本的子对象 /td[2]…然后找到这些的第二个孩子。 在本例中,只有一个符合条件,因此只有一个符合条件,但我们仍然使用at_xpath,以便直接获取该节点,而不是包含单个元素的节点集

这里和任何屏幕抓取的目标都是锁定页面上有意义的值,而不是任意索引

例如,我可以将table1 xpath编写为:

# Find the first table with this summary
table1 = doc.at_xpath('//table[@summary="Inspections"][1]')
……甚至

# Find the 20th table on the page
//table[20]
然而,这些都是脆弱的。如果有人向页面中添加新的节,或者添加或删除格式表的代码,则会导致这些表达式中断。您希望搜索可能不会更改的强属性和文本,并在此基础上锚定搜索


车辆检查XPath同样脆弱,依赖于行的顺序而不是行的标签文本。

这里是我试图获取信息的示例页面:我正在查看两个主要的数据表:个人数据和下面的检查/碰撞表。我将更新上面的选择器,以显示我正在使用的和不起作用的内容。@demondeac11太好了,这很有帮助。我编辑了我的答案,以得到我认为您想要的答案,解释了XPath的工作原理,这样您也许可以手工创建自己的查询,并试图描述为什么使用基于索引的CSS选择器太脆弱。老实说,这是我收到的关于堆栈溢出的最佳答案。这是一个让我困惑了一段时间的问题,我很高兴您不仅向我展示了如何解决它,而且还向我展示了如何使用xpath,这样我就可以自己解决未来的问题。当然,这是我试图从中获取信息的示例页面:我正在获取两个主要的数据表,个人数据及其下方的检查/碰撞表。我将更新上面的选择器,以显示我正在使用的和不起作用的内容。@demondeac11太好了,这很有帮助。我编辑了我的答案,以得到我认为您想要的答案,解释了XPath的工作原理,这样您也许可以手工创建自己的查询,并试图描述为什么使用基于索引的CSS选择器太脆弱。老实说,这是我收到的关于堆栈溢出的最佳答案。这是一个困扰了我一段时间的问题,我很高兴您不仅向我展示了如何解决它,而且还展示了如何使用xpath,这样我就可以自己解决未来的问题。请添加一些示例HTML来演示这个问题。如果URL指向的页面消失,您的问题将不会真正帮助将来遇到此问题的任何人。请添加一些示例HTML来演示此问题。如果URL指向的页面消失,您的问题将不会真正帮助将来遇到问题的任何人。