我在使用 Nokogiri gem 进行一些 HTML 抓取和解析的 Ruby 脚本时遇到了字符编码问题。在脚本中的某一时刻,我对从某些 HTML 中提取的字符串数组调用 join("n")
,这会导致此错误:
./script.rb:333:in `join': incompatible character encodings: UTF-8 and ASCII-8BIT (Encoding::CompatibilityError)
在我的日志中,我可以看到一些将包含在连接操作中的字符串Café
显示。
是不是我的数组中的一些字符串是 ASCII-8BIT 和一些是 UTF-8 并且 ruby 不能组合它们?在使用 Nokogiri 解析字符串(转换为 UTF-8)后,我是否需要转换或清理我的字符串?
在对抓取的 HTML 内容执行任何其他操作之前,我尝试force_encoding('UTF-8')
并encode('UTF-8')
它,但它没有帮助。事实上,在我尝试encode('UTF-8')
之后,我的脚本在包含Café
的字符串上调用to_s
时崩溃得更早。
字符编码总是让我感到困惑。我还能做些什么来清理字符串以避免此错误吗?
编辑:
我最近在Perl中做了类似的事情,并使用了一个名为Text::Unidecode
的模块,并且能够将我的字符串传递给一个函数,该函数可以翻译任何有问题的字符,例如字母a
与急性到普通字母a
。红宝石有什么类似的吗?(不过,这不一定是我的目标,如果我能保持急性的a,那么我认为这是可取的。
编辑2:我对此感到非常困惑,事实证明很难可靠地复制。下面是一些代码:
[CODE REMOVED]
编辑3:
我删除了之前发布的代码示例,因为它不正确。但最重要的是,每当我尝试在被抓取的字符串上打印或调用to_s
时,我都会收到编码错误。
编辑4:
最终事实证明,抓取的html输入并不是导致问题的原因。每当我尝试在包含抓取的 html 文本等内容的哈希上打印或调用to_s时,我都会收到编码错误。"其他内容"是来自数据库查询的值,它们以 ASCII-8BIT
返回。为了解决这个问题,我明确地必须对我使用的每个数据库值调用 force_encoding('UTF-8')
(尽管我听说 mysql2
gem 会自动执行此操作,因此我应该切换到该值)。
我讨厌字符编码。
据推测,Café
应该是Café
.如果我们从 UTF-8 的Café
开始,但将字节视为以 ISO-8859-1(又名拉丁语-1)编码,然后将它们重新编码为 UTF-8,我们会得到您所看到的Café
;例如:
> s = 'Café'
=> "Café"
> s.encoding
=> #<Encoding:UTF-8>
> s.force_encoding('iso-8859-1').encode('utf-8')
=> "Café"
因此,您在某处读取 UTF-8 字符串,但将其视为拉丁语 1 并将其重新编码为 UTF-8。我猜Nokogiri正在阅读页面并认为它是拉丁语-1,或者您的用户代理告诉它正在获取拉丁语-1文本。也许您在某处的默认编码不正确,或者 HTTP 标头对编码撒谎,或者页面本身对其编码撒谎。
您需要将所有内容放入刮板边缘的 UTF-8 中。找出谁在编码上撒谎并在那里进行整理。
不要感到难过,抓取和编码是混乱、愚蠢、猜测和烈酒的噩梦。服务器撒谎,页面撒谎,浏览器撒谎,没有人高兴。