10

我有一个执行以下操作的 Sinatra 应用程序 ( http://analyzethis.espace-technologies.com )

  1. 检索 HTML 页面(通过 net/http)
  2. 从 response.body 创建一个 Nokogiri 文档
  3. 提取一些信息并将其发送回响应中。响应应该是 UTF-8 编码的

因此,我在尝试阅读使用 windows-1256 编码的网站(如 www.filfan.com 或 www.masrawy.com)时遇到了问题。

问题是编码转换的结果不正确,尽管没有抛出错误。

net/http response.body.encoding 给出的 ASCII-8BIT 不能转换为 UTF-8

如果我执行 Nokogiri::HTML(response.body) 并使用 css 选择器从页面获取某些内容 - 例如标题标签的内容 - 我得到一个字符串,当我调用 string.encoding 返回 WINDOWS-1256 . 我使用 string.encode("utf-8") 并使用它发送响应,但响应再次不正确。

关于我的方法有什么问题有什么建议或想法吗?

4

2 回答 2

27

因为 Net::HTTP 不能正确处理编码。见http://bugs.ruby-lang.org/issues/2567

您可以解析response['content-type']包含字符集的内容,而不是解析整个response.body.

然后使用force_encoding()设置正确的编码。

response.body.force_encoding("UTF-8")如果网站以 UTF-8 提供。

于 2012-12-08T17:03:12.693 回答
3

我发现以下代码现在对我有用

def document
  if @document.nil? && response
    @document = if document_encoding
                  Nokogiri::HTML(response.body.force_encoding(document_encoding).encode('utf-8'),nil, 'utf-8')
                else
                  Nokogiri::HTML(response.body)
                end
  end
  @document
end

def document_encoding
  return @document_encoding if @document_encoding
  response.type_params.each_pair do |k,v|
    @document_encoding = v.upcase if k =~ /charset/i
  end
  unless @document_encoding
    #document.css("meta[http-equiv=Content-Type]").each do |n|
    #  attr = n.get_attribute("content")
    #  @document_encoding = attr.slice(/charset=[a-z1-9\-_]+/i).split("=")[1].upcase if attr
    #end
    @document_encoding = response.body =~ /<meta[^>]*HTTP-EQUIV=["']Content-Type["'][^>]*content=["'](.*)["']/i && $1 =~ /charset=(.+)/i && $1.upcase
  end
  @document_encoding
end 
于 2009-08-02T00:43:15.620 回答