是的,那個錯誤意味着你的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頁面或相關代碼段,並描述您想要的元素/文本/屬性,我們可以告訴您如何選擇它。
更新:我在該頁面上看到6個表格。哪個是「碰撞率/檢查」表?鑑於您的網址最終包含#Inspections
,我假設您正在討論「Inspections/Crashes In US」部分下方的兩個表格。以下是匹配的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查詢可能看起來很嚇人。讓我來解釋他們是如何工作的:
//table[@summary="Inspections"][preceding::h4[.//a[@name="Inspections"]]]
//table
在文檔
[@summary="Inspections"]
的任何級別找到<table>
......但只有當它有一個summary
屬性與此值
[preceding::h4…]
......只有當你能更早的文檔中找到一個<h4>
元素
[.//a…]
...具體地說,<h4>
有一個<a>
某處它的下面
[@name="Inspections"]
...這<a>
必須有一個name
屬性與此文本。
這實際上匹配兩個表(還有另一個summary="Inspections"
表後面的頁面上),但使用at_xpath
找到的第一個匹配表。
.//tr[2]/td
.
在當前節點開始(此表)
//tr[2]
...找到第二<tr>
即在任何級別
/td
後代......和然後找到那個<td>
的孩子。
同樣,因爲我們使用的是at_xpath
,所以我們找到第一個匹配的<td>
。
.//tr[th="Out of Service"]/td[2]
.
在當前節點開始(此表)
//tr
...找到任何<tr>
即在任何級別
[th="Out of Service]
後代......但只有那些<tr>
有一個<th>
孩子本文
/td[2]
...然後找到那些第二<td>
孩子。
在這種情況下,只有一個<tr>
符合條件,因而僅匹配一個<td>
,但我們仍然使用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]
然而,這些都是脆弱。有人在頁面上添加新節,或者添加或移除格式表的代碼會導致這些表達式中斷。您想要搜索可能不會更改的強屬性和文本,並根據該文字進行搜索。
0123pXPath同樣很脆弱,依賴於行的排序而不是行的標籤文本。
請添加一些示例HTML顯示問題。如果URL指向的頁面將消失,您的問題將不會真正幫助任何人在將來遇到問題。 –