2010-04-03 48 views
23

Tôi đang sử dụng Nokogiri và open-uri để lấy nội dung của thẻ tiêu đề trên trang web nhưng gặp sự cố với các ký tự có dấu. Cách tốt nhất để giải quyết những vấn đề này là gì? Đây là những gì tôi đang làm:Nokogiri, open-uri và Unicode Ký tự

require 'open-uri' 
require 'nokogiri' 

doc = Nokogiri::HTML(open(link)) 
title = doc.at_css("title") 

Tại thời điểm này, danh hiệu trông như thế này:

Rag \ 303 \ 271

Thay vì:

Ragù

Làm thế nào tôi có thể có nokogiri trả về ký tự thích hợp (ví dụ: ù trong trường hợp này)?

Dưới đây là một URL ví dụ:

http://www.epicurious.com/recipes/food/views/Tagliatelle-with-Duck-Ragu-242037

+0

Nó sẽ hỗ trợ cho những người giúp đỡ nếu chúng tôi có thể có URL đến trang web để chúng tôi có thể kiểm tra nó. –

+0

Làm thế nào để bạn kiểm tra tiêu đề sau đó và phiên bản Ruby bạn đang sử dụng? 'Rag \ 303 \ 271' _is_' Ragù' UTF-8 được mã hóa. –

+0

Xin chào Mladen, tôi đang sử dụng Ruby 1.8.6. Tôi đang kiểm tra tiêu đề từ giao diện điều khiển tương tác của Ruby. Cuối cùng, nó kết thúc được lưu trữ trong cơ sở dữ liệu MySQL. Một khi trong MySQL nó trông giống như: ¹ – Moe

Trả lời

10

Khi bạn nói "trông như thế này," được bạn xem giá trị IRB này? Nó sẽ loại bỏ các ký tự không thuộc phạm vi ASCII với việc thoát kiểu C của các chuỗi byte đại diện cho các ký tự.

Nếu bạn in chúng bằng cách đặt, bạn sẽ lấy lại chúng như bạn mong đợi, giả sử bảng điều khiển vỏ của bạn đang sử dụng cùng một mã hóa như chuỗi đang đề cập (Dường như UTF-8 trong trường hợp này, dựa trên hai byte được trả về cho nhân vật đó). Nếu bạn đang lưu trữ các giá trị trong một tập tin văn bản, việc in một tay cầm cũng sẽ dẫn đến các chuỗi UTF-8.

Nếu bạn cần dịch giữa UTF-8 và các mã hóa khác, chi tiết cụ thể tùy thuộc vào việc bạn đang ở trong Ruby 1.9 hay 1.8.6.

Đối với 1,9: http://blog.grayproductions.net/articles/ruby_19s_string cho 1,8, bạn có thể cần phải xem Iconv.

Ngoài ra, nếu bạn cần phải tương tác với các thành phần COM trong Windows, bạn sẽ cần phải nói với ruby ​​sử dụng mã hóa đúng với một cái gì đó như sau:

require 'win32ole' 

WIN32OLE.codepage = WIN32OLE::CP_UTF8 

Nếu bạn đang tương tác với mysql, bạn sẽ cần đặt collation trên bảng thành bảng có hỗ trợ mã hóa mà bạn đang làm việc. Nói chung, tốt nhất là đặt collation thành UTF-8, ngay cả khi một số nội dung của bạn quay trở lại trong các mã hóa khác; bạn sẽ chỉ cần chuyển đổi nếu cần.

Nokogiri có một số tính năng để xử lý các mã hóa khác nhau (có thể thông qua Iconv), nhưng tôi hơi thiếu thực hành với điều đó, vì vậy tôi sẽ để lại lời giải thích cho người khác.

+0

Hi Jason, Cảm ơn rất nhiều vì tất cả sự giúp đỡ. Có nó hoạt động hoàn hảo. Tôi đặt mã hóa MySQL DB của tôi thành UTF-8 cũng như hồ sơ thiết bị đầu cuối của tôi. – Moe

+0

@Moe Điều này có thể là 'xử lý' vấn đề, hoặc nó có thể che giấu nó. Xem câu trả lời của tôi về cách đảm bảo sạch rằng Nokogiri đang nhận được nội dung UTF-8 phù hợp. – Phrogz

1

Bạn cần phải chuyển đổi các phản ứng từ các trang web đang được cạo (ở đây epicurious.com) vào utf-8 mã hóa.

theo nội dung html từ trang đang được cạo, "ISO-8859-1" hiện tại của nó.Vì vậy, bạn cần phải làm điều gì đó như thế này:

require 'iconv' 
doc = Nokogiri::HTML(Iconv.conv('utf-8//IGNORE', 'ISO-8859-1', open(link).read)) 

đọc thêm về nó ở đây: http://www.quarkruby.com/2009/9/22/rails-utf-8-and-html-screen-scraping

+0

Từ mẫu được cung cấp, rõ ràng là nội dung của anh ấy đã có trong UTF-8. – JasonTrue

+0

không phải vậy. nếu không thì anh ta sẽ chỉ nhận được ù. trang web không được mã hóa utf-8 – Nakul

+0

\ 303 \ 271 là các giá trị byte UT-8 được c-thoát, đó là cách chúng xuất hiện trong IRB khi bạn xem chuỗi được đánh giá; đó là bát phân cho C3 B9, là chuỗi UTF-8 cho ù. Nếu nó là iso-8859-1, anh ta sẽ nhận được bát phân cho F9, hoặc \ 371. – JasonTrue

6

Hãy thử thiết lập các tùy chọn mã hóa của Nokogiri, như vậy:

require 'open-uri' 
require 'nokogiri' 
doc = Nokogiri::HTML(open(link)) 
doc.encoding = 'utf-8' 
title = doc.at_css("title") 
56

Tóm tắt: Khi cho UTF-8 vào Nokogiri thông qua open-uri, hãy sử dụng open(...).read và chuyển chuỗi kết quả đến Nokogiri.

Phân tích: Nếu tôi lấy trang sử dụng curl, các tiêu đề đúng cách hiển thị Content-Type: text/html; charset=UTF-8 và nội dung tập tin bao gồm giá trị UTF-8, ví dụ "Genealogía de Jesucristo". Nhưng ngay cả với một bình luận kỳ diệu vào file Ruby và thiết lập mã hóa doc, đó là không tốt:

# encoding: UTF-8 
require 'nokogiri' 
require 'open-uri' 

doc = Nokogiri::HTML(open('http://www.biblegateway.com/passage/?search=Mateo1-2&version=NVI')) 
doc.encoding = 'utf-8' 
h52 = doc.css('h5')[1] 
puts h52.text, h52.text.encoding 
#=> Genealogà a de Jesucristo 
#=> UTF-8 

Chúng ta có thể thấy rằng đây không phải là lỗi của mở uri:

html = open('http://www.biblegateway.com/passage/?search=Mateo1-2&version=NVI') 
gene = html.read[/Gene\S+/] 
puts gene, gene.encoding 
#=> Genealogía 
#=> UTF-8 

Đây là một vấn đề Nokogiri khi giao dịch với open-uri, có vẻ như vậy. Điều này có thể được giải quyết bằng cách chuyển HTML dưới dạng chuỗi thô tới Nokogiri:

# encoding: UTF-8 
require 'nokogiri' 
require 'open-uri' 

html = open('http://www.biblegateway.com/passage/?search=Mateo1-2&version=NVI') 
doc = Nokogiri::HTML(html.read) 
doc.encoding = 'utf-8' 
h52 = doc.css('h5')[1].text 
puts h52, h52.encoding, h52 == "Genealogía de Jesucristo" 
#=> Genealogía de Jesucristo 
#=> UTF-8 
#=> true 
+0

cảm ơn bạn đã giúp tôi một lần nữa :) –

+0

Cảm ơn rất nhiều vì câu trả lời này! –

+1

Wow, tôi không bao giờ có thể đã tìm ra rằng việc bổ sung '.read' sẽ sửa lỗi này. Cảm ơn bạn! – g33kz0r

36

Tôi gặp vấn đề tương tự và cách tiếp cận Iconv không hoạt động. Nokogiri::HTML là bí danh cho Nokogiri::HTML.parse(thing, url, encoding, options).

Vì vậy, bạn chỉ cần thực hiện:

doc = Nokogiri::HTML(open(link).read, nil, 'utf-8')

và nó sẽ chuyển đổi mã hóa trang đúng cách để utf-8. Bạn sẽ thấy Ragù thay vì Rag\303\271.

0

Mẹo: bạn cũng có thể sử dụng đá quý Scrapifier để nhận siêu dữ liệu, làm tiêu đề trang, từ URI theo cách rất đơn giản. Tất cả dữ liệu được mã hóa bằng UTF-8.

Hãy khám phá: https://github.com/tiagopog/scrapifier

Hy vọng nó hữu ích cho bạn.

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