27

I'm using Nokogiri and open-uri to grab the contents of the title tag on a webpage, but am having trouble with accented characters. What's the best way to deal with these? Here's what I'm doing:

require 'open-uri'
require 'nokogiri'

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

At this point, the title looks like this:

Rag\303\271

Instead of:

Ragù

How can I have nokogiri return the proper character (e.g. ù in this case)?

Here's an example URL:

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

4

8 回答 8

62

总结:通过 open-uri 将 UTF-8 输入到 Nokogiri 时,使用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
于 2011-01-15T20:47:21.413 回答
36

我遇到了同样的问题,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.

于 2011-01-24T13:37:24.540 回答
11

当你说“看起来像这样”时,你是在查看这个值 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),但我对此有点不习惯,所以我会把它的解释留给其他人。

于 2010-04-03T20:06:52.127 回答
6

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

require 'open-uri'
require 'nokogiri'
doc = Nokogiri::HTML(open(link))
doc.encoding = 'utf-8'
title = doc.at_css("title")
于 2010-07-31T15:50:00.303 回答
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

于 2010-04-04T08:21:07.093 回答
1

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

(链接中的重音字符在两者中都很好,所以不知道这是否对您有帮助。)

例子:

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"
于 2019-12-15T18:24:23.887 回答
0

只是为了添加一个交叉引用,这个 SO 页面提供了一些相关信息:

如何使 Nokogiri 透明地返回未触及的未编码的 Html 实体?

于 2010-04-04T00:45:47.313 回答
0

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

看看:https ://github.com/tiagopog/scrapifier

希望它对你有用。

于 2014-04-09T14:57:42.817 回答