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
Ответы
Ответ 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
Ответ 6
Чтобы добавить перекрестную ссылку, эта страница SO содержит некоторую связанную информацию:
Как сделать Nokogiri прозрачно возвращать un/закодированные объекты Html нетронутыми?
Ответ 7
Совет:, вы также можете использовать жемчужину Scrapifier, чтобы получить метаданные, как заголовок страницы, из URI очень простым способом. Все данные кодируются в UTF-8.
Проверьте это: https://github.com/tiagopog/scrapifier
Надеюсь, что это будет полезно для вас.