open-uri从iso-8859编码的网页返回ASCII-8BIT

我正在使用open-uri来阅读声称在iso-8859-1中编码的网页。 当我读取页面内容时,open-uri返回以ASCII-8BIT编码的字符串。

open("http://www.nigella.com/recipes/view/DEVILS-FOOD-CAKE-5310") {|f| p f.content_type, f.charset, f.read.encoding } => ["text/html", "iso-8859-1", #] 

我猜这是因为网页的字节(或字符)\ x92不是有效的iso-8859字符。 http://en.wikipedia.org/wiki/ISO/IEC_8859-1 。

我需要将网页存储为utf-8编码文件。 关于如何处理编码不正确的网页的任何想法。 我可以捕获exception并尝试猜测正确的编码,但这看起来很麻烦且容易出错。

  • ASCII-8BIT is an alias for BINARY
  • open-uri做了一件有趣的事情:如果文件小于10kb(或类似的东西),它返回一个String ,如果它更大,那么它返回一个StringIO 。 如果您正在尝试处理编码问题,那可能会令人困惑。

如果文件不是很大,我建议手动将它们加载到字符串中:

 require 'uri' require 'net/http' require 'net/https' uri = URI.parse url_to_file http = Net::HTTP.new(uri.host, uri.port) if uri.scheme == 'https' http.use_ssl = true # possibly useful if you see ssl errors # http.verify_mode = ::OpenSSL::SSL::VERIFY_NONE end body = http.start { |session| session.get uri.request_uri }.body 

然后你可以使用https://rubygems.org/gems/ensure-encoding gem

 require 'ensure/encoding' utf8_body = body.ensure_encoding('UTF-8', :external_encoding => :sniff, :invalid_characters => :transcode) 

我对ensure-encoding感到非常满意…我们在http://data.brighterplanet.com的生产中使用它

请注意,您还可以说:invalid_characters => :ignore而不是:transcode

此外,如果您以某种方式知道编码,您可以传递:external_encoding => 'ISO-8859-1'而不是:sniff