Nokogiri, open-uri и Unicode символы - PullRequest
       32

Nokogiri, open-uri и Unicode символы

25 голосов
/ 03 апреля 2010

Я использую Nokogiri и open-uri для захвата содержимого тега title на веб-странице, но у меня проблемы с акцентированными символами. Какой лучший способ справиться с этим? Вот что я делаю:

require 'open-uri'
require 'nokogiri'

doc = Nokogiri::HTML(open(link))
title = doc.at_css("title")

На данный момент заголовок выглядит так:

Rag \ 303 \ 271

Вместо:

рагу

Как я могу дать нокогири вернуть правильный символ (например, ù в данном случае)?

Вот пример URL:

http://www.epicurious.com/recipes/food/views/Tagliatelle-with-Duck-Ragu-242037

Ответы [ 7 ]

61 голосов
/ 15 января 2011

Резюме: При подаче UTF-8 в Нокогири через open-uri, используйте open(...).read и передайте полученную строку в Нокогири.

Анализ: Если я получаю страницу с помощью curl, заголовки правильно показывают Content-Type: text/html; charset=UTF-8, а содержимое файла содержит действительный UTF-8, например, "Genealogía de Jesucristo". Но даже с волшебным комментарием к файлу Ruby и настройкой кодировки doc, это бесполезно:

# 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

Мы видим, что это не вина 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

Это проблема Нокогири, когда дело касается open-uri. Это можно обойти, передав HTML-код в виде необработанной строки в 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
36 голосов
/ 24 января 2011

У меня была та же проблема, и подход Iconv не работал. Nokogiri::HTML является псевдонимом Nokogiri::HTML.parse(thing, url, encoding, options).

Итак, вам просто нужно сделать:

doc = Nokogiri::HTML(open(link).read, nil, 'utf-8')

и он будет правильно преобразовывать кодировку страницы в utf-8. Вы увидите Ragù вместо Rag\303\271.

11 голосов
/ 04 апреля 2010

Когда вы говорите «выглядит так», вы просматриваете это значение IRB? Он будет избегать символов диапазона, отличных от ASCII, с экранированием байтовых последовательностей, которые представляют символы в стиле C.

Если вы печатаете их с путами, вы получите их обратно, как и ожидаете, предполагая, что ваша консоль оболочки использует ту же кодировку, что и рассматриваемая строка (очевидно, в данном случае UTF-8, основываясь на двух байтах, возвращаемых для этот персонаж). Если вы сохраняете значения в текстовом файле, печать на дескриптор также должна приводить к последовательностям UTF-8.

Если вам необходимо выполнить перевод между UTF-8 и другими кодировками, особенности зависят от того, используете ли вы Ruby 1.9 или 1.8.6.

Для 1,9: http://blog.grayproductions.net/articles/ruby_19s_string для 1.8 вам, вероятно, нужно взглянуть на Iconv.

Кроме того, если вам нужно взаимодействовать с COM-компонентами в Windows, вам нужно указать ruby ​​использовать правильную кодировку, например:

require 'win32ole'

WIN32OLE.codepage = WIN32OLE::CP_UTF8

Если вы взаимодействуете с mysql, вам нужно установить в таблице параметры сортировки, которые поддерживают кодировку, с которой вы работаете. В общем случае лучше установить сопоставление в UTF-8, даже если часть вашего контента возвращается в других кодировках; вам просто нужно конвертировать по мере необходимости.

У Нокогири есть некоторые особенности для работы с различными кодировками (вероятно, через Iconv), но я немного не практикую в этом, поэтому я оставлю объяснение этому кому-то еще.

6 голосов
/ 31 июля 2010

Попробуйте установить кодировку Nokogiri, например так:

require 'open-uri'
require 'nokogiri'
doc = Nokogiri::HTML(open(link))
doc.encoding = 'utf-8'
title = doc.at_css("title")
1 голос
/ 04 апреля 2010

Вам необходимо преобразовать ответ с очищаемого веб-сайта (здесь epicurious.com) в кодировку utf-8.

согласно html-содержимому с очищаемой страницы, его "ISO-8859-1"" теперь.Итак, вам нужно сделать что-то вроде этого:

require 'iconv'
doc = Nokogiri::HTML(Iconv.conv('utf-8//IGNORE', 'ISO-8859-1', open(link).read))

Подробнее об этом здесь: http://www.quarkruby.com/2009/9/22/rails-utf-8-and-html-screen-scraping

0 голосов
/ 09 апреля 2014

Совет: Вы также можете использовать гем Scrapifier для получения метаданных в качестве заголовка страницы из URI очень простым способом. Все данные закодированы в UTF-8.

Проверьте это: https://github.com/tiagopog/scrapifier

Надеюсь, это полезно для вас.

0 голосов
/ 04 апреля 2010

Просто чтобы добавить перекрестную ссылку, эта SO-страница дает некоторую связанную информацию:

Как сделать так, чтобы Nokogiri прозрачно возвращал не закодированные сущности HTML нетронутыми?

...