ошибки преобразования символов ruby ​​1.9 при тестировании регулярных выражений - PullRequest
0 голосов
/ 10 марта 2012

Я знаю, что существует множество документов и дискуссий, но все же:

Это моя лучшая попытка на моей попытке Rails протестировать данные с разных сайтов. Странный факт, что если я вручную скопирую и вставлю источник URL-адреса, все пойдет хорошо.

Что я могу сделать?

# encoding: utf-8

require 'rubygems'
require 'iconv'
require 'nokogiri'
require 'open-uri'
require 'uri'

url = 'http://www.website.com/url/test'

sio = open(url)
@cur_encoding = sio.charset
doc = Nokogiri::HTML(sio, nil, @cur_encoding)
txtdoc = doc.to_s

# 1) String manipulation test
p doc.search('h1')[0].text # "Nove36  "
p doc.search('h1')[0].text.strip! # nil <- ERROR


# 2) Regex test
# txtdoc = "test test 44.00 € test test" # <- THIS WORKS
regex = "[0-9.]+ €"


p /#{regex}/i =~ txtdoc # integer expected

Я понимаю, что, вероятно, моя ОС Ubuntu плюс мой текстовый редактор делает хорошее преобразование кодировки по сравнению с, возможно, неработающей кодировкой: это нормально, НО как я могу исправить эту проблему в моем приложении во время работы вживую?

Ответы [ 2 ]

3 голосов
/ 10 марта 2012

@ cur_encoding = doc.encoding # ISO-8859-15

ISO-8859-15 не является правильной кодировкой для указанной страницы; это должен был быть UTF-8. иконка в UTF-8, как будто это 8859-15, только усугубляет проблему.

Эта кодировка исходит из неисправного тега <meta> в документе. Браузер игнорирует этот тег и использует переопределенную кодировку из заголовка ответа HTTP Content-Type: text/html;charset=utf-8.

Однако, похоже, Нокогири не может прочитать этот заголовок из потока open() ed. С предупреждением о том, что я ничего не знаю о Ruby, при поиске источника может показаться, что проблема заключается в том, что он использует свойство encoding из string-or-IO вместо charset, которое, по-видимому, и пишется open-uri.

Вы можете передать собственную кодировку переопределения, поэтому я думаю, попробуйте:

sio= open(url)
doc= Nokogiri::HTML.parse(doc, nil, sio.charset) # should be UTF-8?
2 голосов
/ 11 марта 2012

Проблемы, с которыми вы столкнулись, вызваны неразрывными пробелами (Unicode U + 00A0) на странице.

В вашей первой задаче строка:

"Nove36  "

на самом деле заканчивается U + 00A0, а String#strip! не считает этот символ пробелом для удаления:

1.9.3-p125 :001 > s = "Foo \u00a0"
 => "Foo  " 
1.9.3-p125 :002 > s.strip
 => "Foo  "    #unchanged

В вашей второй проблеме пробел между ценой и знаком евро снова является неразрывным пробелом, поэтому регулярное выражение просто не совпадает с поиском нормального пробела:

# s as before
1.9.3-p125 :003 > s =~ /Foo  / #2 spaces, no match
 => nil 
1.9.3-p125 :004 > s =~ /Foo /  #1 space, match
 => 0 
1.9.3-p125 :005 > s =~ /Foo \u00a0/  #space and non breaking space, match
 => 0

Когда вы копируете и вставляете исходный код, браузер, вероятно, нормализует неразрывные пробелы, поэтому вы копируете только символ обычного пробела, поэтому он работает таким образом.

Простейшим решением будет глобальная замена пространства \u00a0 перед началом обработки:

sio = open(url)
@cur_encoding = sio.charset

txt = sio.read             #read the whole file
txt.gsub! "\u00a0", " "    #global replace

doc = Nokogiri::HTML(txt, nil, @cur_encoding)   #use this new string instead...
...