使用open-uri时编码:: UndefinedConversionError

时间:2014-07-24 14:27:00

标签: ruby open-uri

当我这样做时:

require 'open-uri'
response = open('some-html-page-url-here')
response.read

在某个网址上我收到以下错误(由于返回的网址中的编码错误?!):

Encoding::UndefinedConversionError: U+00A0 from UTF-8 to US-ASCII

有什么方法可以获得html内容吗?

3 个答案:

答案 0 :(得分:3)

在open-uri模块的介绍中,文档说这个,

  

可以打开http,https或ftp URL,就好像它是一个文件

如果你对阅读文件有所了解,那么你必须知道你想要阅读的文件的编码。您需要知道编码,以便告诉ruby如何读取文件(即每个字符占用多少字节(或多少空间))。

在文档的第一个代码示例中,有:

  open("http://www.ruby-lang.org/en") {|f|
    f.each_line {|line| p line}
    p f.base_uri         # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/>
    p f.content_type     # "text/html"
    p f.charset          # "iso-8859-1"
    p f.content_encoding # []
    p f.last_modified    # Thu Dec 05 02:45:02 UTC 2002
  }

因此,如果您不知道您尝试阅读的“文件”的编码,则可以使用f.charset获取编码。如果该编码与您的default external encoding不同,则很可能会出错。您的default external encoding是ruby用于从外部源读取的编码。您可以检查您的默认外部编码设置如下:

  

从您的环境中提取默认的外部编码...有一个   看:

$ echo $LC_CTYPE
en_US.UTF-8

$ ruby -e 'puts Encoding.default_external.name'
UTF-8

http://graysoftinc.com/character-encodings/ruby-19s-three-default-encodings

在Mac OSX上,我实际上必须执行以下操作才能看到默认的外部编码:

$ echo $LANG

您可以使用Encoding.default_external=()方法设置默认外部编码,因此您可能需要尝试以下方法:

  open('some_url_here') do |f|
    Encoding.default_external = f.charset
    html = f.read
  end

将IO对象设置为binmode,就像你所做的那样,告诉ruby文件的编码是BINARY(或ruby令人困惑的同义词ASCII-8BIT),这意味着你告诉ruby文件中的每个字符占用一个字节。在你的情况下,你告诉ruby读取字符U + 00A0,其UTF-8表示占用两个字节0xC2 0xA0,作为两个字符而不是一个字符,所以你已经消除了你的错误,但你有产生了两个垃圾字符而不是原始字符。

答案 1 :(得分:2)

response.binmode停止发生错误之前执行response.read

答案 2 :(得分:1)

如果出现同样的问题,请在此处添加我的解决方案:

在进一步阅读open-uri文档之后,事实证明你可以在使用set_encoding方法阅读之前设置io的编码,如下所示:

result = open('some-page-uri') do |io|
  io.set_encoding(Encoding.default_external)
  io.read
end

希望它有所帮助!