2011-08-22 28 views
5

Tôi là một người mới lập trình để tha thứ cho sự mới mẻ của tôi. Vì vậy, tôi đang sử dụng Nokogiri để cạo một bản ghi tội phạm của cảnh sát. Đây là mã bên dưới:Nokogiri: Chạy vào lỗi "phương thức không xác định" văn bản "cho nil: NilClass"

require 'rubygems' 
require 'nokogiri' 
require 'open-uri' 

url = "http://www.sfsu.edu/~upd/crimelog/index.html" 
doc = Nokogiri::HTML(open(url)) 
puts doc.at_css("title").text 
doc.css(".brief").each do |brief| 
puts brief.at_css("h3").text 
end 

Tôi đã sử dụng dấu trang tiện ích bộ chọn để tìm bộ chọn CSS cho nhật ký (.brief). Khi tôi vượt qua "h3" thông qua brief.at_css tôi nhận được tất cả các thẻ h3 với nội dung bên trong.

Tuy nhiên, nếu tôi thêm phương thức .text để xóa thẻ, tôi sẽ gặp lỗi NoMethod.

Có lý do nào khiến điều này xảy ra không? Tôi đang thiếu gì? Cảm ơn!

Trả lời

8

Để làm rõ nếu bạn xem cấu trúc của nguồn HTML, bạn sẽ thấy rằng lần xuất hiện đầu tiên của <div class="brief"> không có thẻ con h3 (thẻ này thực sự chỉ có thẻ con <p>).

Các Nokogiri Docs nói rằng

at_css (* quy tắc)

Search nút này để xảy ra đầu tiên của quy tắc CSS. Tương đương với css (quy tắc) .first Xem Node # css để biết thêm thông tin.

Nếu bạn gọi at_css(*rules), tài liệu tuyên bố nó tương đương với css(rules).first. Khi có các mục (lớp .brief của bạn có chứa một h3) sau đó một đối tượng Nokogiri::XML::Element được trả về mà đáp ứng text, trong khi nếu .brief của bạn không chứa một h3 sau đó một đối tượng NilClass được trả lại, trong đó tất nhiên không đáp ứng với text

vì vậy, nếu chúng ta gọi là css(rules) (không at_css là bạn có), chúng tôi được một đối tượng Nokogiri::XML::NodeSet trở lại, trong đó có các text() phương pháp định nghĩa là (chú ý alias)

# Get the inner text of all contained Node objects 
    def inner_text 
    collect{|j| j.inner_text}.join('') 
    end 
    alias :text :inner_text 

bởi vì lớp học là Enumerable nó lặp lại trên đó là trẻ em gọi phương thức inner_text của chúng và tham gia tất cả chúng lại với nhau.

Vì vậy bạn có thể thực hiện một kiểm tra nil? hoặc như @floatless tuyên bố một cách chính xác chỉ cần sử dụng các phương pháp css

+0

Tuyệt vời đã làm điều đó! Cám ơn rất nhiều! – aboutaaron

4

Bạn chỉ cần thay thế at_css bằng css và mọi thứ sẽ ổn.

+0

Trừ rằng 'css' trả về một nodeset, nơi 'at_css' trả về một Node, vì vậy nodeset sẽ cần phải được lặp lại. –

+0

Ngoại trừ bạn cũng có thể gọi #inner_text trên NodeSet. Cho dù nó sẽ làm những gì bạn muốn phụ thuộc vào những gì bạn muốn xảy ra khi có> 1 trận đấu. Nếu luôn có chỉ 0 hoặc 1, nó có thể sẽ làm những gì bạn muốn. – jrochkind

Các vấn đề liên quan