2011-02-01 149 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')