Nokogiri,open-uri和Unicode角色

时间:2010-04-03 19:28:44

标签: ruby unicode screen-scraping nokogiri open-uri

我正在使用Nokogiri和open-uri来抓取网页上标题标签的内容,但是在重音字符方面遇到了麻烦。处理这些问题的最佳方法是什么?这就是我正在做的事情:

require 'open-uri'
require 'nokogiri'

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

此时,标题如下所示:

  

拉​​格\ 303 \ 271

而不是:

  

肉酱

我怎样才能让nokogiri返回正确的字符(例如在这种情况下为ù)?

以下是一个示例网址:

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

8 个答案:

答案 0 :(得分:60)

摘要:当通过open-uri向UTok-8提供UTF-8时,请使用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时,这是一个Nokogiri问题。这可以通过将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

答案 1 :(得分:36)

我遇到了同样的问题而且Iconv方法无效。 Nokogiri::HTMLNokogiri::HTML.parse(thing, url, encoding, options)的别名。

所以,你只需要这样做:

doc = Nokogiri::HTML(open(link).read, nil, 'utf-8')

它会将页面编码正确转换为utf-8。您会看到Ragù而不是Rag\303\271

答案 2 :(得分:10)

当您说“看起来像这样”时,您是否正在查看此值IRB?它将通过C样式转义表示字符的字节序列来转义非ASCII范围字符。

如果你使用puts打印它们,你会按照你的预期将它们恢复,假设你的shell控制台使用与相关字符串相同的编码(在这种情况下显然是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。

此外,如果您需要与Windows中的COM组件进行交互,则需要告诉ruby使用正确的编码,如下所示:

require 'win32ole'

WIN32OLE.codepage = WIN32OLE::CP_UTF8

如果您正在与mysql交互,则需要将表上的排序规则设置为支持您正在使用的编码的排序规则。通常,最好将排序规则设置为UTF-8,即使您的某些内容以其他编码方式返回;你只需要根据需要进行转换。

Nokogiri有一些处理不同编码的功能(可能是通过Iconv),但我对此有点不合理,所以我会把这个解释给别人。

答案 3 :(得分:6)

尝试设置Nokogiri的编码选项,如下所示:

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

答案 4 :(得分:1)

您需要将被抓取的网站(此处为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

答案 5 :(得分:0)

只需添加交叉引用,此SO页面会提供一些相关信息:

How to make Nokogiri transparently return un/encoded Html entities untouched?

答案 6 :(得分:0)

提示:您还可以使用Scrapifier gem以非常简单的方式从URI获取元数据作为页面标题。数据均以UTF-8编码。

检查出来:https://github.com/tiagopog/scrapifier

希望它对你有用。

答案 7 :(得分:0)

将Nokogiri :: HTML (...)更改为Nokogiri :: HTML5 (...)已解决了我解析某些特殊字符(特别是em)时遇到的问题-破折号。

(链接中带重音符号的字符都很好用,所以不知道这样做是否对您有帮助。)

示例:

url = 'https://www.youtube.com/watch?v=4r6gr7uytQA'

doc = Nokogiri::HTML(open(url))
doc.title
=> "Josh Waitzkin â\u0080\u0094 How to Cram 2 Months of Learning into 1 Day | The Tim Ferriss Show - YouTube"

doc = Nokogiri::HTML5(open(url))
doc.title
=> "Josh Waitzkin — How to Cram 2 Months of Learning into 1 Day | The Tim Ferriss Show - YouTube"