2011-12-06 12 views
2

Nokogiriを使用してウェブサイトを掻き集め、テーブルからフィールドを取得しようとすると問題に遭遇しています。私はselector gadgetを使ってテーブルのCSSセレクタを探しています。私はgovernment website that details information on motor carriersからデータを取得しています。Nokogiriでウェブサイトを掻き立てる

私はのようなルックスを使用しています方法:しかし、私はクラッシュ率/点検で問題が生じています、私はその構文を使用して、上の表内のすべてのフィールドを取得し、この方法はうまく動作し

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 

下のテーブル。ここで

が、私はその情報をつかむために使用していますものです:私はこれの端からtextを削除した場合

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

undefined method `text' for nil:NilClass 

、方法が実行されますが(明らかに)任意の関連情報をつかむしません。私は、フィールドを取得するために使用している複雑なセレクタが原因であると想定していますが、あまり確実ではありません。

誰もが同様の問題に遭遇していますか?私に助言をお願いしますか?

+0

問題を示すサンプルHTMLを追加してください。 URLが指すページが消えてしまった場合、あなたの質問は将来問題が発生した人には本当に役立つものではありません。 –

答えて

4

はい、そのエラーは、CSSセレクタが情報を検出していないことを意味します。 at_cssnilを返し、nil.textは無効です。

insp = doc.at_css("long example css selector") 
self.vehicle_inspections = insp && insp.text 

しかし、あなたはこのデータを「必要とする」ように聞こえます。あなたはHTMLページやCSSセレクタを提供していないので、実際のCSSやXPathセレクタを作る手助けはできません。

今後の質問や、このコードの編集では、実際の(弱った)コードは、手を振るよりも強く、コードがどのように見えるのかがはっきりしていることに注意してください。 HTMLページや関連するスニペットを表示して、どの要素/テキスト/属性を記述したら、どのように選択するかを教えてください。

更新:このページには6つの表があります。 「衝突率/検査」テーブルはどれですか?あなたのURLに最後に#Inspectionsが含まれているとすれば、私はあなたが「Inspections/Crashes In US」セクションのすぐ下の2つのテーブルについて話していると仮定しています。それぞれに一致する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クエリは恐ろしく見えるかもしれません。私は、彼らがどのように動作するかを説明しましょう:

  1. //table[@summary="Inspections"][preceding::h4[.//a[@name="Inspections"]]]

    • //table文書
    • [@summary="Inspections"]の任意のレベルで<table>を見つける...それはこれでsummary属性を持つ場合にのみ、値
    • [preceding::h4…] ...とだけあなたが<h4>要素以前の文書
    • [.//a…]で見つけることができるかどうか...どこか
      • [@name="Inspections"] ...と<a>nameを有していなければならないことの下<a>があり、特に、<h4>このテキストの属性。

    これは実際には2つのテーブルを(別のsummary="Inspections"表がページに後であります)と一致しますが、at_xpathを使用すると、最初に一致したテーブルを見つけます。現在のノード(この表)

  2. //tr[2]で開始

  3. .//tr[2]/td

    • . ...任意のレベル
    • /tdに子孫である<tr>秒を見つける...とその子供の<td>が見つかりました。

    また、at_xpathを使用しているため、最初の一致は<td>です。現在のノード(この表)

  4. //trで開始

  5. .//tr[th="Out of Service"]/td[2]

    • . ...任意のレベル
      • [th="Out of Service]に子孫である任意<tr>を見つける...しかし<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] 

。誰かがページに新しいセクションを追加したり、フォーマットテーブルを追加または削除したりするコードでは、それらの式が壊れてしまいます。おそらく変化しない強力な属性やテキストを探して、それに基づいて検索を固定したいとします。

vehicle_inspections XPathも同様に脆弱で、行のラベルテキストではなく行の順序に依存します。

+0

ここからは、情報を取得しようとしているページの例があります。[safer](http://safer.fmcsa.dot.gov/query.asp?searchtype=ANY&&query_type=queryCarrierSnapshot&query_param=USDOT&query_string=800789)私が把握しているデータの表、その下の個人データと検査/クラッシュテーブル。上記のセレクタを更新して、私が使っているものと動作していないものを表示します。 – tomciopp

+0

@ demondeac11素晴らしいです。私はあなたが望むものを得るために自分の答えを編集しました。XPathがどのようにして独自のクエリを作成できるかを説明し、インデックスに基づいてCSSセレクタを使用するのがなぜ壊れやすいのかを説明しようとしました。 – Phrogz

+0

@Phrogz +1ありがとう、あなたの説明は私を助けてくれました – Hishalv

関連する問題