我有一个Ruby脚本的字符编码问题,它使用Nokogiri gem进行一些HTML抓取和解析。在脚本的某一点上,我在从某些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')
之后,我的脚本在包含to_s
的字符串上调用Café
时甚至更早崩溃。
字符编码总是让我感到困惑。我还能做些什么来清理字符串以避免这个错误?
修改
我最近在Perl中做了类似的事情并使用了一个名为Text::Unidecode
的模块,并且能够将我的字符串传递给一个翻译任何有问题的字符的函数,例如字母为a
的字母a
。红宝石有什么相似之处吗? (这不一定是我瞄准的目标,但如果我能保持急性,那么我认为这更好。
EDIT2:
我真的对此感到困惑,并且证明难以可靠地再现。这里有一些代码:
[CODE REMOVED]
EDIT3:
我删除了以前发布的代码示例,因为它不正确。但最重要的是,每当我尝试打印或在被抓取的字符串上调用to_s
时,我都会遇到编码错误。
Edit4:
事实证明,刮掉的html输入并不是导致问题的原因。每当我尝试打印或在包含其他内容的已删除的html文本的哈希上调用to_s时,我都会遇到编码错误。其他事情'是来自数据库查询的值,它们是在ASCII-8BIT
中返回的。为了解决这个问题,我明确地不得不在我使用的每个数据库值上调用force_encoding('UTF-8')
(虽然我听说mysql2
gem会自动执行此操作,因此我应该切换到该值。)
我讨厌字符编码。
答案 0 :(得分:2)
据推测,Café
应该是Café
。如果我们从UTF-8中的Café
开始,但将字节视为在ISO-8859-1(AKA Latin-1)中编码,然后将它们重新编码为UTF-8,我们得到{ {1}}你正在看到的;例如:
Café
所以在某处您正在读取UTF-8字符串但将其视为Latin-1并将其重新编码为UTF-8。我猜Nokogiri正在阅读该页面并认为它是Latin-1或被您的用户代理告知它正在获取Latin-1文本。也许你的某个地方有一个错误的默认编码,或者HTTP标题是关于编码的,或者页面本身就是关于它的编码。
你需要在刮刀边缘将所有东西都装入UTF-8。找出谁对编码撒谎并在那里排序。
不要感觉不好,刮痧和编码是混乱,愚蠢,猜测和烈酒的噩梦。服务器谎言,页面谎言,浏览器谎言,没有人幸福。