2011-02-01 45 views
34

Tôi đang kéo văn bản từ các trang web từ xa và cố gắng tải nó vào ứng dụng Ruby 1.9/Rails 3 sử dụng utf-8 theo mặc định.Chuyển đổi các ký tự không phải ASCII từ ASCII-8BIT sang UTF-8

Dưới đây là một ví dụ về một số văn bản vi phạm:

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

Đó là mã bản quyền mở rộng như thế này:

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

của Ruby nói với tôi chuỗi được mã hóa như ASCII-8 bit và ăn vào của tôi Ứng dụng Rails mang lại cho tôi điều này:

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

Tôi có thể xóa mã bản quyền bằng cách sử dụng lại gex

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

để sản xuất này

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

Nhưng làm thế nào tôi có thể nhận được một biểu tượng quyền tác giả (và nhiều biểu tượng khác như thư từ Hy Lạp) chuyển vào cùng một biểu tượng trong UTF-8? Chắc chắn nó có thể ...

tôi thấy tài liệu tham khảo để sử dụng force_encoding nhưng điều này không làm việc:

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

Tôi nhận ra có rất nhiều người khác với vấn đề tương tự nhưng tôi chưa thấy một giải pháp mà công trinh.

+1

Bạn kéo văn bản từ các trang web từ xa như thế nào? Cạo trang? Vui lòng hiển thị một số mã mẫu, bao gồm cả ứng dụng khách HTTP mà bạn đang sử dụng và liệu bạn có đang phân tích cú pháp các trang bằng Nokogiri, Hpricot hoặc ReXML hay không. Vấn đề này có thể là kết quả của cách bạn truy xuất trang và/hoặc cách bạn phân tích trang. Khi chúng tôi biết bạn đang kéo nội dung theo cách an toàn dữ liệu, chúng tôi có thể giúp bạn chuyển đổi dữ liệu giữa các bộ mã. –

+0

Mã đơn giản thực sự - mở-uri và nokogiri - ví dụ: doc = Nokogiri :: XML (mở (url)) rồi văn bản doc.css (...) để kéo các khối văn bản có liên quan –

+1

Vui lòng hiển thị mã mẫu. Tệp bạn đang truy xuất HTML hay XML? Nokogiri quan tâm đến sự khác biệt khi phân tích cú pháp. Ngoài ra, hãy cung cấp một số URL, bởi vì mọi trang web trên internet đều khác nhau. –

Trả lời

54

này làm việc cho tôi:

#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> 
+0

Cảm ơn! Điều này rất hữu ích. – Mike

+5

Điều này có thể dẫn đến 'chuỗi byte không hợp lệ trong lỗi UTF-8'. Tôi sẽ đề nghị bạn sử dụng 'encode ('UTF-8')' thay thế. – jpemberthy

+0

Điều đó cũng phù hợp với tôi, nhưng các chuỗi khác thì không. Ví dụ: str = "Diario El d \ xEDa Bolivia" sẽ không chuyển thành "Diario El día Bolivia". –

6

tôi sử dụng để làm việc này cho một kịch bản mà cạo trang Hy Lạp Windows mã hóa, sử dụng mở uri, iconv và Hpricot:

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

Tôi tin đó là Ruby 1.8.7, không chắc chắn mọi thứ bằng ruby ​​như thế nào 1.9

+0

Cảm ơn bạn! Không ai trong số trên đã được xử lý "\ x96" cho tôi, vẫn sẽ thổi lên. Iconv.conv ('utf- 8 ', "WINDOWS-1253", str) làm việc hoàn hảo. – spilliton

+0

Bạn cũng có thể cần đặt giá trị 'phiên âm' của Iconv thành true. Http://ruby-doc.org/stdlib-1.9.2/libdoc/iconv/rdoc /Iconv.html#method-i-transliterate-3D – wmarbut

23

Có hai khả năng:

  1. Dữ liệu đầu vào đã là UTF-8, nhưng Ruby không biết điều đó. Điều đó có vẻ là trường hợp của bạn, vì "\ xC2 \ xA9" là hợp lệ UTF-8 cho biểu tượng bản quyền. Trong trường hợp này, bạn chỉ cần nói với Ruby rằng dữ liệu đã được UTF-8 sử dụng force_encoding.

    Ví dụ "\ xC2 \ xA9" .force_encoding ('ASCII-8BIT') sẽ tạo lại bit có liên quan của dữ liệu đầu vào của bạn. Và "\ xC2 \ xA9". Force_encoding ('ASCII-8BIT'). Force_encoding ('UTF-8') sẽ chứng minh rằng bạn có thể nói với Ruby rằng nó thực sự là UTF-8 và có được kết quả mong muốn.

  2. Dữ liệu đầu vào nằm trong một số mã hóa khác và bạn cần Ruby chuyển mã sang UTF-8. Trong trường hợp đó, bạn phải nói cho Ruby biết mã hóa hiện tại là gì (ASCII-8BIT là ruby-speak cho nhị phân, nó không phải là mã hóa thực), sau đó yêu cầu Ruby chuyển mã nó.

    Ví dụ: giả sử dữ liệu đầu vào của bạn là ISO-8859-1. Trong đó mã hóa biểu tượng bản quyền chỉ là "\ xA9". Điều này sẽ tạo ra một lượng dữ liệu như vậy: "\ xA9" .force_encoding ('ISO-8859-1') Và điều này sẽ chứng minh rằng bạn có thể làm cho Ruby chuyển mã sang UTF-8: "\ xA9" .force_encoding ('ISO -8859-1 ').encode ('UTF-8')

+0

Tôi đã nhận được loại lỗi này với máy chủ rails + sql. Giải quyết cài đặt "mã hóa: ISO-8859-1" trong database.yml và sử dụng "lating string" .encode ("UTF-8") –

+0

Hoàn hảo # 2 giải quyết vấn đề của tôi, kéo qua Ruby/DBI từ Sql Server cũng @ Lucas Renan: Cảm ơn bạn đã đứng đầu trên đường ray/database.yml. – jetimms

Các vấn đề liên quan