HttpWebRequest:使用正确的编码接收响应

时间:2009-03-12 14:06:48

标签: encoding .net-2.0 httpwebrequest

我目前正在使用以下代码下载HTML页面:

Try
    Dim req As System.Net.HttpWebRequest = DirectCast(WebRequest.Create(URL), HttpWebRequest)
    req.Method = "GET"
    Dim resp As Net.HttpWebResponse = DirectCast(req.GetResponse(), Net.HttpWebResponse)
    Dim stIn As IO.StreamReader = New IO.StreamReader(resp.GetResponseStream())
    Dim strResponse As String = stIn.ReadToEnd

    ''Clean up
    stIn.Close()
    stIn.Dispose()
    resp.Close()

    Return strResponse

Catch ex As Exception
    Return ""
End Try

这适用于大多数页面,但对于某些页面(例如:www.gap.com),我得到错误编码的响应。
例如,在gap.com中,我将“”改为“?” 更不用说如果我尝试加载google.cn会发生什么......

我在这里缺少什么,让.Net对此进行编码?

我最担心的是,我实际上必须读取HTML中指定编码的元标记,然后重新读取(重新编码?)整个流。

任何指针都将非常感激。


更新

感谢John Saunders的回复,我离我更近一点了。 HttpWebResponse.ContentEncoding属性似乎总是​​空的。但是,HttpWebResponse.CharacterSet似乎很有用,有了这段代码,我就越来越近了:

Dim resp As Net.HttpWebResponse = DirectCast(req.GetResponse(), Net.HttpWebResponse)
Dim respEncoding As Encoding = Encoding.GetEncoding(resp.CharacterSet)
Dim stIn As IO.StreamReader = New IO.StreamReader(resp.GetResponseStream(), respEncoding)

现在Google.cn与所有中文字符完美结合 但是,Gap.Com仍然出错了。

对于Gap.com,HttpWebResponse.CharacterSet是ISO-8859-1,我通过GetEncoding获取的编码是{System.Text.Latin1Encoding},其中的主体名称为“ISO-8859-1”,AND HTML中的Content-Type META标记指定为“charset = ISO-8859-1”。

我还在做错什么吗? 或者GAP做错了什么?

3 个答案:

答案 0 :(得分:2)

我相信HttpWebResponse有一个ContentEncoding属性。在StreamReader的构造函数中使用它。

答案 1 :(得分:1)

Gap的网站错了。具体问题是他们的页面声称编码为Latin1(ISO-8859-1),而页面使用的字符#146在ISO-8859-1中无效。

然而,该字符在Windows CP-1252编码(ISO 8859-1的超集)中有效。在CP-1252中,字符代码#146用于右引号字符。你会在今天的Gap.com主页上的文章中看到这是“你会发现娇小和小尺寸”的撇号。

您可以阅读 http://en.wikipedia.org/wiki/Windows-1252了解详情。事实证明,这种事情是网页上常见的问题,其中内容最初是以CP-1252编码保存的(例如,从Word复制/粘贴)。

故事的道德:始终将国际化文本作为Unicode存储在数据库中,并始终在Web服务器上以HTML格式发出HTML!

答案 2 :(得分:0)

丹尼尔, 有些页面甚至没有返回CharacterSet中的值,因此这种方法不太可靠。 有时甚至连浏览器都无法“猜测”使用哪种编码,所以我认为你不能做100%的enconding识别。

在我的特殊情况下,当我处理西班牙语或葡萄牙语页面时,我使用 UTF7 编码,它对我来说很好(áéíóúñÑêã...等)。

可能是您可以先加载一个CharacterSet代码表及其相应的编码。如果CharacterSet为空,您可以提供默认编码。

detectEncodingFromByteOrderMarks构造函数中的StreamReader参数可能会有所帮助,因为它会自动检测或推断出第一个字节的某些编码。