Pregunta

He aquí una muestra de algunas rarezas:

#!/usr/bin/ruby

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

print "without read: ", Nokogiri(open('http://weblog.rubyonrails.org/')).class, "\n"
print "with read:    ", Nokogiri(open('http://weblog.rubyonrails.org/').read).class, "\n"

Al ejecutar este devuelve:

without read: Nokogiri::XML::Document
with read:    Nokogiri::HTML::Document

Sin el XML devuelve read, y con ella es HTML? La página Web se define como "XHTML de transición", por lo que en un principio pensé Nokogiri debe haber sido la lectura de "Content-Type" de OpenURI de la corriente, pero que devuelve 'text/html':

(rdb:1) doc = open(('http://weblog.rubyonrails.org/'))
(rdb:1) doc.content_type
"text/html"

que es lo que el servidor está regresando. Por lo tanto, ahora estoy tratando de averiguar por qué Nokogiri está regresando dos valores diferentes. No parece ser analizar el texto y el uso de la heurística para determinar si el contenido es HTML o XML.

Lo mismo está sucediendo con el canal de información ATOM apuntado por esa página:

(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
(rdb:1) doc.class
Nokogiri::XML::Document

(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails').read)
(rdb:1) doc.class
Nokogiri::HTML::Document

Tengo que ser capaz de analizar una página sin saber lo que es por adelantado, ya sea HTML o una alimentación (RSS o ATOM) y fiable determinar qué es. Pregunté Nokogiri para analizar el cuerpo ya sea de un archivo HTML o XML feed, pero estoy viendo los resultados inconsistentes.

pensé que podría escribir algunas pruebas para determinar el tipo, pero luego me encontré con XPaths no encontrar elementos, pero las búsquedas regulares de trabajo:

(rdb:1) doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
(rdb:1) doc.class
Nokogiri::XML::Document
(rdb:1) doc.xpath('/feed/entry').length
0
(rdb:1) doc.search('feed entry').length
15
XPaths

que pensé sería trabajar con XML, pero los resultados no parecen dignos de confianza tampoco.

Estas pruebas se puede hacer todo en mi caja de Ubuntu, pero he visto el mismo comportamiento en mi Macbook Pro. Me gustaría saber que estoy haciendo algo mal, pero no he visto un ejemplo para el análisis y la búsqueda de que me dio resultados consistentes. ¿Alguien puede mostrar el error de mis maneras?

¿Fue útil?

Solución

Tiene que ver con la forma de analizar método funciona. Aquí está la fuente:

# File lib/nokogiri.rb, line 55
    def parse string, url = nil, encoding = nil, options = nil
      doc =
        if string =~ /^\s*<[^Hh>]*html/i # Probably html
          Nokogiri::HTML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_HTML)
        else
          Nokogiri::XML::Document.parse(string, url, encoding, options || XML::ParseOptions::DEFAULT_XML)
        end
      yield doc if block_given?
      doc
    end

La clave es la if string =~ /^\s*<[^Hh>]*html/i # Probably html línea. Cuando sólo tiene que utilizar open, devuelve un objeto que no funciona con expresiones regulares, por lo que siempre devuelve falso. Por otro lado, read devuelve una cadena, por lo que podría ser considerado como HTML. En este caso se trata, ya que coincide con la expresión regular. Aquí está el comienzo de esa cadena:

<!DOCTYPE html PUBLIC

La expresión coincide con el "! DOCTYPE" a [^Hh>]* y luego coincide con el "html", asumiendo así que es HTML. ¿Por qué una persona seleccionada esta expresión regular para determinar si el archivo es HTML está más allá de mí. Con esta expresión regular, un archivo que comienza con una etiqueta como <definitely-not-html> se considera HTML, pero se considera <this-is-still-not-html> XML. Usted es probablemente el mejor de permanecer lejos de esta función muda e invocando Nokogiri::HTML::Document#parse o Nokogiri::XML::Document#parse directamente.

Otros consejos

En respuesta a esta parte de su pregunta:

  

pensé que podría escribir algunas pruebas a   determinar el tipo, pero luego me encontré con   XPaths no encontrar elementos, pero   búsquedas regulares de trabajo:

acabo de venir a través de este problema utilizando nokogiri a analizar un átomo de alimentación. El problema parecía a la declaración de espacio de nombres en el anonimato:

<feed xmlns="http://www.w3.org/2005/Atom">

La eliminación de la declaración xmlns desde el XML de origen permitiría Nokogiri a buscar con XPath como de costumbre. Extracción de que la declaración de la alimentación, obviamente, no era una opción aquí, así que en vez me acaba de quitar los espacios de nombre del documento después del análisis. por ejemplo:

doc = Nokogiri.parse(open('http://feeds.feedburner.com/RidingRails'))
doc.remove_namespaces!
doc.xpath('/feed/entry').length

feo lo sé, pero lo hizo el truco.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top