ruby - Nokogiri, open-uri y personajes Unicode
screen-scraping (7)
Estoy usando Nokogiri y open-uri para tomar el contenido de la etiqueta del título en una página web, pero estoy teniendo problemas con los caracteres acentuados. ¿Cuál es la mejor manera de lidiar con esto? Esto es lo que estoy haciendo:
require ''open-uri''
require ''nokogiri''
doc = Nokogiri::HTML(open(link))
title = doc.at_css("title")
En este punto, el título se ve así:
Rag / 303 / 271
En lugar de:
Ragù
¿Cómo puedo hacer que nokogiri devuelva el carácter apropiado (por ejemplo, ù en este caso)?
Aquí hay una URL de ejemplo:
http://www.epicurious.com/recipes/food/views/Tagliatelle-with-Duck-Ragu-242037
Cuando dices "se ve así", ¿estás viendo este valor IRB? Va a escapar caracteres de rango no ASCII con escape de estilo C de las secuencias de bytes que representan los caracteres.
Si los imprime con puts, los recuperará como espera, suponiendo que su shell shell usa la misma codificación que la cadena en cuestión (aparentemente UTF-8 en este caso, en función de los dos bytes devueltos para ese personaje) . Si está almacenando los valores en un archivo de texto, imprimir en un manejador también debería dar como resultado secuencias UTF-8.
Si necesita traducir entre UTF-8 y otras codificaciones, los detalles dependen de si está en Ruby 1.9 o 1.8.6.
Para 1.9: http://blog.grayproductions.net/articles/ruby_19s_string para 1.8, probablemente necesite mirar Iconv.
Además, si necesita interactuar con componentes COM en Windows, tendrá que decirle a ruby que use la codificación correcta con algo como lo siguiente:
require ''win32ole''
WIN32OLE.codepage = WIN32OLE::CP_UTF8
Si está interactuando con mysql, deberá establecer la intercalación en la tabla a una que admita la codificación con la que está trabajando. En general, es mejor establecer la intercalación en UTF-8, incluso si parte de su contenido vuelve a aparecer en otras codificaciones; solo necesitarás convertir según sea necesario.
Nokogiri tiene algunas características para lidiar con diferentes codificaciones (probablemente a través de Iconv), pero estoy un poco fuera de práctica con eso, así que le dejo la explicación a alguien más.
Estaba teniendo el mismo problema y el enfoque de Iconv no funcionaba. Nokogiri::HTML
es un alias de Nokogiri::HTML.parse(thing, url, encoding, options)
.
Entonces, solo necesitas hacer:
doc = Nokogiri::HTML(open(link).read, nil, ''utf-8'')
y convertirá la codificación de la página correctamente a utf-8. Verás Ragù
lugar de Rag/303/271
.
Intenta configurar la opción de codificación de Nokogiri, así:
require ''open-uri''
require ''nokogiri''
doc = Nokogiri::HTML(open(link))
doc.encoding = ''utf-8''
title = doc.at_css("title")
Necesita convertir la respuesta del sitio web que se está raspando (aquí epicurious.com) en codificación utf-8.
según el contenido html de la página que se está raspando, es "ISO-8859-1" por ahora. Entonces, necesitas hacer algo como esto:
require ''iconv''
doc = Nokogiri::HTML(Iconv.conv(''utf-8//IGNORE'', ''ISO-8859-1'', open(link).read))
Lea más sobre esto aquí: http://www.quarkruby.com/2009/9/22/rails-utf-8-and-html-screen-scraping
Solo para agregar una referencia cruzada, esta página SO proporciona información relacionada:
¿Cómo hacer que Nokogiri devuelva intactas las entidades Html sin codificación?
Consejo: también puede usar la gema Scrapifier para obtener metadatos, como el título de la página, de los URI de una manera muy simple. Todos los datos están codificados en UTF-8.
Échale un vistazo: https://github.com/tiagopog/scrapifier
Espero que sea útil para ti.
Resumen: Al alimentar UTF-8 a Nokogiri a través de open-uri, use open(...).read
y pase la cadena resultante a Nokogiri.
Análisis: si busco la página usando curl, los encabezados muestran apropiadamente Content-Type: text/html; charset=UTF-8
Content-Type: text/html; charset=UTF-8
y el contenido del archivo incluye UTF-8 válido, por ejemplo, "Genealogía de Jesucristo"
. Pero incluso con un comentario mágico en el archivo Ruby y estableciendo la codificación del documento, no sirve:
# encoding: UTF-8
require ''nokogiri''
require ''open-uri''
doc = Nokogiri::HTML(open(''http://www.biblegateway.com/passage/?search=Mateo1-2&version=NVI''))
doc.encoding = ''utf-8''
h52 = doc.css(''h5'')[1]
puts h52.text, h52.text.encoding
#=> Genealogà a de Jesucristo
#=> UTF-8
Podemos ver que esto no es culpa de open-uri:
html = open(''http://www.biblegateway.com/passage/?search=Mateo1-2&version=NVI'')
gene = html.read[/Gene/S+/]
puts gene, gene.encoding
#=> Genealogía
#=> UTF-8
Este es un problema de Nokogiri cuando se trata de open-uri, parece. Esto puede solucionarse pasando el HTML como una cadena sin formato a Nokogiri:
# encoding: UTF-8
require ''nokogiri''
require ''open-uri''
html = open(''http://www.biblegateway.com/passage/?search=Mateo1-2&version=NVI'')
doc = Nokogiri::HTML(html.read)
doc.encoding = ''utf-8''
h52 = doc.css(''h5'')[1].text
puts h52, h52.encoding, h52 == "Genealogía de Jesucristo"
#=> Genealogía de Jesucristo
#=> UTF-8
#=> true