Я пишу краулер на Ruby (1.9), который потребляет много HTML с множества случайных сайтов.
При попытке извлечь ссылки я решил просто использовать .scan(/href="(.*?)"/i)
вместо nokogiri / hpricot (значительное ускорение). Проблема в том, что теперь я получаю много " invalid byte sequence in UTF-8
" ошибок.
Насколько я понял, в net/http
библиотеке нет каких-либо конкретных параметров кодирования, и все, что входит, в основном не помечено должным образом.
Как лучше всего работать с этими входящими данными? Я попытался .encode
установить замену и неверные параметры, но пока безуспешно ...
109
'U*'
отменяет действие'C*'
?Ответы:
В Ruby 1.9.3 можно использовать String.encode, чтобы «игнорировать» недопустимые последовательности UTF-8. Вот фрагмент, который будет работать как в 1.8 ( iconv ), так и в 1.9 ( String # encode ):
или если у вас действительно неприятный ввод, вы можете выполнить двойное преобразование из UTF-8 в UTF-16 и обратно в UTF-8:
источник
file_contents.encode!('UTF-16', 'UTF-8', :invalid => :replace, :replace => '')
file_contents.encode!('UTF-8', 'UTF-16')
force_encoding
. Если вы читаете ISO8859-1 как UTF-8 (и, следовательно, эта строка содержит недопустимый UTF-8), вы можете «переинтерпретировать» его как ISO8859-1 с the_string.force_encoding («ISO8859-1») и просто работать с этой строкой в ее реальной кодировке..encode('UTF-8')
не выполняется, и никакие проверки не выполняются. Документация Ruby Core для кодирования . Однако преобразование его в UTF-16 сначала принудительно запускает все проверки на недопустимые последовательности байтов, а замены выполняются по мере необходимости.Принятый ответ или другой ответ у меня работают. Я нашел этот пост, в котором предлагалось
Это устранило проблему для меня.
источник
Мое текущее решение - запустить:
Это как минимум избавит от исключений, которые были моей основной проблемой.
источник
valid_encoding?
которым, кажется, обнаруживает, что что-то не так.val.unpack('C*').pack('U*') if !val.valid_encoding?
.\xB0
спину в символы градусов. Дажеvalid_encoding?
возвращается правда , но я все еще проверить , если он не делает и вычистить оскорбляющие символы , используя ответ Амира выше:string.encode!('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
. Я тоже пробовал этотforce_encoding
маршрут, но это не удалось.Попробуй это:
источник
Я рекомендую вам использовать парсер HTML. Просто найдите самый быстрый.
Разобрать HTML не так просто, как может показаться.
Браузеры анализируют недопустимые последовательности UTF-8 в HTML-документах UTF-8, просто помещая символ « ». Итак, как только недопустимая последовательность UTF-8 в HTML будет проанализирована, результирующий текст станет допустимой строкой.
Даже внутри значений атрибутов вам нужно декодировать объекты HTML, такие как amp
Вот отличный вопрос, который подводит итог, почему нельзя надежно анализировать HTML с помощью регулярного выражения: RegEx сопоставляет открытые теги, за исключением автономных тегов XHTML.
источник
Кажется, это работает:
источник
источник
Я столкнулся со строкой, в которой были смешаны английский, русский и некоторые другие алфавиты, что вызвало исключение. Мне нужен только русский и английский, и сейчас это работает для меня:
источник
Хотя решение Nakilon работает, по крайней мере, в том, что касается обхода ошибки, в моем случае у меня был этот странный персонаж из Microsoft Excel, преобразованный в CSV, который регистрировался в рубине как (получить) кириллицу K, которая в ruby был выделен жирным шрифтом K. Чтобы исправить это, я использовал iso-8859-1, а именно.
CSV.parse(f, :encoding => "iso-8859-1")
, который превратил мою причудливую кириллицу K в более управляемую/\xCA/
, которую я мог затем удалить с помощьюstring.gsub!(/\xCA/, '')
источник
Перед использованием
scan
убедитесь, что запрошенная страница имеетContent-Type
заголовокtext/html
, поскольку могут быть ссылки на такие вещи, как изображения, которые не закодированы в UTF-8. Страница также может быть не HTML, если вы выбралиhref
что-то вроде<link>
элемента. Как это проверить, зависит от того, какую HTTP-библиотеку вы используете. Затем убедитесь, что результатом является только ascii сString#ascii_only?
(не UTF-8, потому что HTML должен использовать только ascii, в противном случае можно использовать объекты). Если оба эти теста пройдут успешно, пользоваться им безопасноscan
.источник
Если вас не «заботят» данные, вы можете просто сделать что-то вроде:
search_params = params[:search].valid_encoding? ? params[:search].gsub(/\W+/, '') : "nothing"
Я просто
valid_encoding?
проходил мимо. У меня поле поиска, и я снова и снова обнаруживал одну и ту же странность, поэтому использовал что-то вроде: просто чтобы система не сломалась. Поскольку я не контролирую пользовательский интерфейс для автоматической проверки перед отправкой этой информации (например, автоматическая обратная связь, чтобы сказать «пустышка!»), Я могу просто взять ее, вырезать и вернуть пустые результаты.источник