Несовместимые кодировки с ruby ​​и Nokogiri HTML - PullRequest
4 голосов
/ 28 января 2011

Я анализирую внешнюю HTML-страницу с помощью Nokogiri.Эта страница кодируется с ISO-8859-1.Часть данных, которые я хочу извлечь, содержит некоторые - (черточки) html-сущности:

xml = Nokogiri.HTML(open("http://flybynight.com.br/agenda.php"), nil, 'ISO-8859-1')
f = xml.xpath("//div[@style='background-color:#D9DBD9; padding:15px 12px 10px 10px;']//div[@class='tit_inter_cnz']/text()")
f[0].text #=> Preview M/E/C/A \u0096 John Digweed

В последней строке строка должна отображаться в браузере с тире .Браузер корректно отображает его, если я указываю свою страницу в кодировке ISO-8859-1, однако мое приложение Sinatra использует UTF-8.Как правильно отобразить этот текст в браузере?Сегодня это отображается в виде квадрата с небольшим числом внутри.Я пробовал force_encoding ('ISO-8859-1'), но затем я получаю ошибку CompatibilityError от Sinatra.

Есть какие-нибудь подсказки?

[Редактировать] Ниже приведены скриншоты приложения:

-> Firefox с кодировкой символов UTF-8 Firefox with character encoding UTF-8

-> [Firefox с кодировкой символов Western (ISO)-8859-1) Firefox with character encoding Western (ISO-8859-1)

Стоит отметить, что в вышеприведенном режиме ISO-8859-1 тире отображается правильно, но есть еще один неправильный символ с ним непосредственно перед тире.Странно: (

Ответы [ 3 ]

9 голосов
/ 28 января 2011

После анализа документа в Nokogiri вы можете указать, что он принимает другую кодировку .Попробуйте:

require 'open-uri'
require 'nokogiri'
doc = Nokogiri::HTML((open("http://flybynight.com.br/agenda.php"), nil, 'ISO-8859-1')
doc.encoding = 'UTF-8'

Я не вижу этой страницы отсюда, чтобы подтвердить, что это решает проблему, но она работает для подобных проблем.

1 голос
/ 28 января 2011

Сводка : проблемные символы - это управляющие символы из ISO-8859-1, не предназначенные для отображения.

Подробности и расследование :
Вот тест, показывающий, что вы получаете действительный UTF-8 от Нокогири и Синатры:

require 'sinatra'
require 'open-uri'

get '/' do
  html = open("http://flybynight.com.br/agenda.php").read
  p [ html.encoding, html.valid_encoding? ]
  #=> [#<Encoding:ISO-8859-1>, true]

  str  = html[ /Preview.+?John Digweed/ ]
  p [ str, str.encoding, str.valid_encoding? ]
  #=> ["Preview M/E/C/A \x96 John Digweed", #<Encoding:ISO-8859-1>, true]

  utf8 = str.encode('UTF-8')
  p [ utf8, utf8.encoding, utf8.valid_encoding? ]
  #=> ["Preview M/E/C/A \xC2\x96 John Digweed", #<Encoding:UTF-8>, true]

  require 'nokogiri'
  doc = Nokogiri.HTML(html, nil, 'ISO-8859-1')
  p doc.encoding
  #=> "ISO-8859-1"

  dig = doc.xpath("//div[@class='tit_inter_cnz']")[1]
  p [ dig.text, dig.text.encoding, dig.text.valid_encoding? ]
  #=> ["Preview M/E/C/A \xC2\x96 John Digweed", #<Encoding:UTF-8>, true]

  <<-ENDHTML
  <!DOCTYPE html>
  <html><head><title>Dig it!</title></head><body>
  <p>Here it comes...</p>
  <p>#{dig.text}</p>
  </body></html>
  ENDHTML
end

Это правильно отображает содержимое с Content-Type:text/html;charset=utf-8 на моем компьютере. Однако в браузере Chrome этот символ не отображается.

Анализируя этот ответ, та же пара байтов Unicode возвращается для тире, как показано выше: \xC2\x96. Похоже, это этот символ Unicode , который кажется странным тире.

Я бы отнес это к неверным исходным данным и просто бросил:

#encoding: UTF-8

вверху ваших исходных файлов Ruby, а затем вставьте:

f = ...text.gsub( "\xC2\x96", "-" ) # Or a better Unicode character

Редактировать : Если вы посмотрите тестовую страницу браузера для этого символа , вы увидите (по крайней мере, в Chrome и Firefox для меня), что буквенная версия UTF-8 пусто, но отображаются шестнадцатеричная и десятичная версии escape. Я не могу понять, почему это так, но у вас это есть. Браузеры просто не отображают ваш персонаж правильно, когда представлены в необработанном виде.

Либо сделайте его сущностью HTML, либо другой штрих-код Unicode. В любом случае требуется gsub.

Редактировать # 2 : Еще одно странное замечание: символ в исходной кодировке имеет шестнадцатеричное значение байта 0x96. Насколько я могу судить, это не печатный символ ISO-8859-1 . Как показано в официальной спецификации для ISO-8859-1 , это относится к одной из двух непечатных областей.

0 голосов
/ 28 января 2011

Я работаю в издании научных рукописей, и есть много черточек.Черта, которую вы используете, это не ASCII, это Unicode.Принудительное кодирование ISO, вероятно, приводит к изменению тире.

http://www.fileformat.info/info/unicode/char/96/index.htm

Этот сайт отлично подходит для проблем с юникодом.

Причина, по которой вы получаете квадрат, заключается в том, что, возможно, ваш браузер не поддерживает это.Это, вероятно, правильно отображается.Я бы сохранил кодировку UTF-8, и если вы хотите сделать эту черту, чтобы все могли ее видеть, конвертируйте ее в черту ascii.

Вы можете попробовать Iconv для преобразования символов в ASCII / UTF8 http://craigjolicoeur.com/blog/ruby-iconv-to-the-rescue

...