【问题标题】:Encoding::UndefinedConversionError when using open-uri使用 open-uri 时的编码::UndefinedConversionError
【发布时间】:2014-07-24 14:26:59
【问题描述】:

当我这样做时:

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

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

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

有什么办法可以继续获取 html 内容?

【问题讨论】:

    标签: ruby open-uri


    【解决方案1】:

    在 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,作为两个字符而不是一个字符,因此您已经消除了错误,但是您已经产生了两个垃圾字符而不是原始字符。

    【讨论】:

      【解决方案2】:

      response.read 之前执行response.binmode 会阻止错误发生。

      【讨论】:

        【解决方案3】:

        有同样的问题,将在这里添加我的解决方案:

        进一步阅读 open-uri 文档后,发现您可以在读取之前使用set_encoding 方法设置 io 的编码,如下所示:

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

        希望对你有帮助!

        【讨论】:

          猜你喜欢
          • 2012-10-11
          • 2015-02-23
          • 2023-03-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-17
          • 2014-08-26
          • 2017-10-02
          相关资源
          最近更新 更多