Подтвердить что ты не робот

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

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

require 'open-uri'
require 'nokogiri'

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

На этом этапе заголовок выглядит следующим образом:

Rag\303\271

Вместо:

рагу

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

Вот пример URL:

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

4b9b3361

Ответ 1

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

Если вы напечатаете их с помощью puts, вы получите их обратно, как вы ожидаете, полагая, что ваша консоль консоли использует ту же кодировку, что и соответствующая строка (очевидно, 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, даже если часть вашего контента вернется в других кодировках; вам просто нужно будет преобразовать по мере необходимости.

В Nokogiri есть некоторые функции для работы с разными кодировками (возможно, через Iconv), но я немного не разбираюсь в этом, поэтому я оставлю объяснение этому кому-то другому.

Ответ 2

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

Анализ: Если я извлекаю страницу с помощью 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

Ответ 3

У меня была такая же проблема, и подход 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.

Ответ 4

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

require 'open-uri'
require 'nokogiri'
doc = Nokogiri::HTML(open(link))
doc.encoding = 'utf-8'
title = doc.at_css("title")

Ответ 5

Вам нужно преобразовать ответ с очищаемого сайта (здесь 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

Ответ 7

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

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

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