2011-02-01 63 views
34

我从远程站点拉取文本并尝试将其加载到默认情况下使用utf-8的Ruby 1.9/Rails 3应用程序中。将非ASCII字符从ASCII-8BIT转换为UTF-8

下面是一些违规文本的例子:

Cancer Res; 71(3); 1-11. ©2011 AACR.\n 

,版权代码扩展这个样子的:

Cancer Res; 71(3); 1-11. \xC2\xA92011 AACR.\n 

红宝石告诉我该字符串编码为ASCII-8BIT和喂养到我Rails应用程序让我这个:

incompatible character encodings: ASCII-8BIT and UTF-8 

我可以使用此re去掉版权代码GEX

str.gsub(/[\x00-\x7F]/n,'?') 

产生这种

Cancer Res; 71(3); 1-11. ??2011 AACR.\n 

但我怎么能得到一个版权符号(以及各种其他符号,如希腊字母)转换成UTF-8相同的符号?当然,它是可能的...

我看到使用force_encoding引用,但这不起作用:

str.force_encoding('utf-8').encode 

我知道有很多人有类似的问题,但我还没有看到一个解决方案,作品。

+1

你是如何从远端站点拉文本的?刮页面?请显示一些示例代码,包括您正在使用的HTTP客户端,以及是否使用Nokogiri,Hpricot或ReXML解析页面。这个问题可能是你如何检索页面和/或你如何解析页面的结果。一旦我们知道您以数据安全的方式提取内容,我们可以帮助您在代码集之间转换数据。 – 2011-02-01 21:15:01

+0

真正简单的代码 - open-uri和nokogiri - 例如doc = Nokogiri :: XML(open(url))然后doc.css(...).text将文本的相关块取出 – 2011-02-01 21:39:16

+1

请显示示例代码。您正在检索HTML或XML文件吗?解析时,Nokogiri确实在意分歧。另外,请提供一些网址,因为互联网上的每个网站都是不同的。 – 2011-02-01 23:57:59

回答

54

这个工作对我来说:

#encoding: ASCII-8BIT 
str = "\xC2\xA92011 AACR" 
p str, str.encoding 
#=> "\xC2\xA92011 AACR" 
#=> #<Encoding:ASCII-8BIT> 

str.force_encoding('UTF-8') 
p str, str.encoding 
#=> "©2011 AACR" 
#=> #<Encoding:UTF-8> 
6

我曾经是刮希腊的Windows编码网页的脚本做到这一点,采用开放式的URI,的iconv和角度来说,Hpricot:

doc = open(DATA_URL) 
doc.rewind 
data = Hpricot(Iconv.conv('utf-8', "WINDOWS-1253", doc.readlines.join("\n"))) 

我相信这是红宝石1.8.7,不知道如何与红宝石1.9

23

有两种可能性:

  1. 输入数据已经是UTF-8,但Ruby不知道它。这似乎是你的情况,因为“\ xC2 \ xA9”对于版权符号是有效的UTF-8。在这种情况下,您只需使用force_encoding告诉Ruby数据已经是UTF-8。

    例如“\ xC2 \ xA9”.force_encoding('ASCII-8BIT')会重新创建输入数据的相关位。和“\ xC2 \ xA9”.force_encoding('ASCII-8BIT')。force_encoding('UTF-8')将证明您可以告诉Ruby它确实是UTF-8并获得了期望的结果。

  2. 输入数据是在其他编码,你需要Ruby转码为UTF-8。在那种情况下,你必须告诉Ruby当前的编码是什么(ASCII-8BIT是ruby--表示二进制,它不是真正的编码),然后告诉Ruby转码。

    例如,假设您的输入数据是ISO-8859-1。在该编码中,版权符号只是“\ xA9”。这会产生这样一些数据:“\ xA9”.force_encoding('ISO-8859-1')这就表明你可以让Ruby把它转码为UTF-8:“\ xA9”.force_encoding('ISO -8859-1' )。编码('UTF-8')