2011-08-22 20 views
5

Soy un novato para el programador, así que disculpe mi novicia. Así que estoy usando Nokogiri para raspar un registro policial de crímenes. Aquí está por debajo del código:Nokogiri: Se está ejecutando el error "método indefinido 'texto' para 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 

que utiliza el bookmarklet dispositivo selector para encontrar el selector CSS para el registro (.brief). Cuando paso "h3" a través de brief.at_css consigo todas las etiquetas h3 con el contenido dentro.

Sin embargo, si agrego el método .text para eliminar las etiquetas, aparece el error NoMethod.

¿Hay alguna razón para que esto suceda? ¿Qué me estoy perdiendo? ¡Gracias!

Respuesta

8

Para aclarar si nos fijamos en la estructura del código fuente HTML se verá que la primera aparición de <div class="brief"> no tiene una etiqueta de niño h3 (que en realidad sólo tiene un código hijo <p>).

El Nokogiri Docs decir que

at_css (* reglas)

Buscar en este nodo para la primera aparición de reglas CSS. Equivalente a css (reglas) .primero Consulte Nodo # css para obtener más información.

Si llama al at_css(*rules), los documentos indican que es equivalente a css(rules).first. Cuando hay más elementos (la clase .brief contiene una h3), entonces un objeto Nokogiri::XML::Element se devuelve el cual responde a text, mientras que si su .brief no contiene una h3 continuación, un objeto NilClass se devuelve, lo que por supuesto no responde a text

Así que si llamamos css(rules) (no at_css ya que tienes) obtenemos un objeto devuelto Nokogiri::XML::NodeSet, que tiene el método definido como text() (nótese la alias)

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

porque la clase es Enumerable itera sobre sus hijos llamando a su método inner_text y los une a todos.

Por lo tanto usted puede realizar una comprobación nil? o como @floatless declaró correctamente sólo tiene que utilizar el método css

+0

¡Impresionante que lo hizo! ¡Muchas gracias! – aboutaaron

4

Sólo necesita reemplazar at_css con css y todo debería estar bien.

+0

Excepto que 'css' devuelve un conjunto de nodos, donde' at_css' devuelve un nodo, por lo que el conjunto de nodos tendrá que ser repetido. –

+0

Excepto que también puede llamar a #inner_text en un NodeSet. Si hará lo que quiere depende de lo que quiere que suceda cuando haya> 1 coincidencia. Si siempre hay solo 0 o 1, probablemente haga lo que quiera. – jrochkind

Cuestiones relacionadas