Ruby 已抓取的字符编码问题 HTML
Ruby character encoding issue with scraped HTML
我遇到了一个 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')
之后,当我的脚本在包含 Café
.
的字符串上调用 to_s
时甚至更早崩溃了
字符编码总是让我很困惑。我还能做些什么来清理字符串以避免此错误吗?
编辑:
我最近在 Perl 中做了类似的事情并使用了一个名为 Text::Unidecode
的模块并且能够将我的字符串传递给一个函数来翻译任何有问题的字符,例如字母 a
与普通字母 a
的锐音符。 ruby 有类似的东西吗? (虽然这不一定是我的目标,但我认为如果我能保持 a 为 acute 则更好。
编辑2:
我真的对此感到困惑,事实证明很难可靠地复制它。这是一些代码:
[CODE REMOVED]
编辑3:
我删除了之前发布的代码示例,因为它不正确。但最重要的是,每当我尝试在被抓取的字符串上打印或调用 to_s
时,我都会收到编码错误。
编辑4:
最后证明,抓取的 html 输入并不是导致问题的原因。每当我尝试打印或调用包含 html 文本的散列时,我都会遇到编码错误。 'other things' 是来自数据库查询的值,它们在 ASCII-8BIT
中返回。为了解决这个问题,我明确地必须在我使用的每个数据库值上调用 force_encoding('UTF-8')
(尽管我听说 mysql2
gem 会自动执行此操作,所以我应该切换到那个)。
我讨厌字符编码。
据推测,Café
应该是Café
。如果我们从 UTF-8 中的 Café
开始,但将字节视为以 ISO-8859-1(也称为 Latin-1)编码,然后将它们 re-encode 视为 UTF-8,我们得到您看到的 Café
;例如:
> s = 'Café'
=> "Café"
> s.encoding
=> #<Encoding:UTF-8>
> s.force_encoding('iso-8859-1').encode('utf-8')
=> "Café"
所以在某处您正在读取 UTF-8 字符串,但将其视为 Latin-1 而 re-encoding 将其视为 UTF-8。我猜 Nokogiri 正在阅读该页面并认为它是 Latin-1,或者您的用户代理告诉它正在获取 Latin-1 文本。也许您在某个地方使用了错误的默认编码,或者 HTTP headers 在编码方面撒谎,或者页面本身在其编码方面撒谎。
您需要将所有内容都转换为 UTF-8 格式的内容。找出谁在编码方面撒谎,然后立即解决。
不要难过,抓取和编码是一场混乱、愚蠢、猜测和烈酒的噩梦。服务器说谎,页面说谎,浏览器说谎,没有人高兴。
我遇到了一个 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')
之后,当我的脚本在包含 Café
.
to_s
时甚至更早崩溃了
字符编码总是让我很困惑。我还能做些什么来清理字符串以避免此错误吗?
编辑:
我最近在 Perl 中做了类似的事情并使用了一个名为 Text::Unidecode
的模块并且能够将我的字符串传递给一个函数来翻译任何有问题的字符,例如字母 a
与普通字母 a
的锐音符。 ruby 有类似的东西吗? (虽然这不一定是我的目标,但我认为如果我能保持 a 为 acute 则更好。
编辑2:
我真的对此感到困惑,事实证明很难可靠地复制它。这是一些代码:
[CODE REMOVED]
编辑3:
我删除了之前发布的代码示例,因为它不正确。但最重要的是,每当我尝试在被抓取的字符串上打印或调用 to_s
时,我都会收到编码错误。
编辑4:
最后证明,抓取的 html 输入并不是导致问题的原因。每当我尝试打印或调用包含 html 文本的散列时,我都会遇到编码错误。 'other things' 是来自数据库查询的值,它们在 ASCII-8BIT
中返回。为了解决这个问题,我明确地必须在我使用的每个数据库值上调用 force_encoding('UTF-8')
(尽管我听说 mysql2
gem 会自动执行此操作,所以我应该切换到那个)。
我讨厌字符编码。
据推测,Café
应该是Café
。如果我们从 UTF-8 中的 Café
开始,但将字节视为以 ISO-8859-1(也称为 Latin-1)编码,然后将它们 re-encode 视为 UTF-8,我们得到您看到的 Café
;例如:
> s = 'Café'
=> "Café"
> s.encoding
=> #<Encoding:UTF-8>
> s.force_encoding('iso-8859-1').encode('utf-8')
=> "Café"
所以在某处您正在读取 UTF-8 字符串,但将其视为 Latin-1 而 re-encoding 将其视为 UTF-8。我猜 Nokogiri 正在阅读该页面并认为它是 Latin-1,或者您的用户代理告诉它正在获取 Latin-1 文本。也许您在某个地方使用了错误的默认编码,或者 HTTP headers 在编码方面撒谎,或者页面本身在其编码方面撒谎。
您需要将所有内容都转换为 UTF-8 格式的内容。找出谁在编码方面撒谎,然后立即解决。
不要难过,抓取和编码是一场混乱、愚蠢、猜测和烈酒的噩梦。服务器说谎,页面说谎,浏览器说谎,没有人高兴。