您的位置:首页 > 理论基础 > 计算机网络

C# HttpWebRequest访问页面时自动识别编码

2015-02-08 20:55 756 查看

C# HttpWebRequest访问页面时自动识别编码

有时候难免会用到需要去访问页面内容的时候 然后就习惯性的先百度一下 C#如何根据一个URL去访问一个页面的内容 百度出来有很多结果 直接复制一个方法下来就用 但是那些方法普遍都存在一个问题 就是页面内容的编码 不是在方法中写死的就是 方法需要接收一个Encoding参数进去 最开始我也没有在意写死就写死呗 反正我都是用代码去访问固定的页面 那个页面什么编码我就填写什么编码 直到有一天需要编写一个爬虫的时候 反正这样子行不通的 不可能固定一个编码进去每个网站的编码不一定都是一样的 所以需要自己去获取编码了
然后又去网上找了一下 怎么自动识别编码 感觉都不靠谱 然后就自己研究了一下

先来看看最开始我的写法 大概是下面这样的代码:

public static string GetUrlHtml(string strUrl, Encoding encoding, int nTimeOut) {
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebRespones = null;
string strHtml = string.Empty;
if (!Regex.IsMatch(strUrl, @"^https?://", RegexOptions.IgnoreCase))
strUrl = "http://" + strUrl;
httpWebRequest = WebRequest.Create(strUrl) as HttpWebRequest;
httpWebRequest.Timeout = nTimeOut;
httpWebRequest.ReadWriteTimeout = 60000;
httpWebRequest.AllowAutoRedirect = true;
httpWebRequest.UserAgent =
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; Maxthon 2.0)";
httpWebRespones = (HttpWebResponse)httpWebRequest.GetResponse();
//判断页面类型 如果不是页面返回空字符
if (httpWebRespones.ContentType.ToLower().IndexOf("text/html") == -1) {
httpWebRespones.Close();
return string.Empty;
}
using (Stream stream = httpWebRespones.GetResponseStream()) {
//这里的encoding是传进来的 和写死没有什么区别
using (StreamReader reader = new StreamReader(stream, encoding)) {
strHtml = reader.ReadToEnd();
}
}
return strHtml;
}

然后我就在想能不能不直接用StreamReader去直接读取文本类容 而是直接把数据读取到一个byte[]数组里面 当然这些数据是文本类容的二进制形式 如果可以这样那就好办多了 就可以通过Encoding.GetString()来得到文本类容 大不了我解码两次 先用随便用一个编码去解码就算是乱码 英文和数字也会保持原样 这就够了 因为我要在里面去匹配 charset 之类的东西通常一些页面不都有一个meta标签吗 里面有指定编码 然后我在里面获取到了正确的编码后 再用获取到的编码来重新解码Encoding.GetEncoding(charset).GetString()这样就能搞定了
然后我就开始研究了一下那个stream我想把里面的数据直接保存到一个byte[]里面去 而不是给一个StreamReader 我看到Stream有一个Length的属性 然后我就在想 既然有长度那我就可以创建一个指定长度的byte[]然后再用Stream的Read方法把数据读取进去 不过貌似程序运行的时候取Length的时候会报错 然后我发现有ReadByte方法 貌似可以使用 但是这个东西只能读取出一个byte然后我创建了一个List来保存byte最后在ToArray()就行了

大概代码如下:

public static string GetUrlHtml(string strUrl, int nTimeOut) {
HttpWebRequest httpWebRequest = null;
HttpWebResponse httpWebRespones = null;
string strHtml = string.Empty;
if (!Regex.IsMatch(strUrl, @"^https?://", RegexOptions.IgnoreCase))
strUrl = "http://" + strUrl;
httpWebRequest = WebRequest.Create(strUrl) as HttpWebRequest;
httpWebRequest.Timeout = nTimeOut;
httpWebRequest.ReadWriteTimeout = 60000;
httpWebRequest.AllowAutoRedirect = true;
httpWebRequest.UserAgent =
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; Maxthon 2.0)";
httpWebRespones = (HttpWebResponse)httpWebRequest.GetResponse();
if (httpWebRespones.ContentType.ToLower().IndexOf("text/html") == -1) {
httpWebRespones.Close();
return string.Empty;
}
using (Stream stream = httpWebRespones.GetResponseStream()) {
List<byte> lst = new List<byte>();
int nRead = 0;
while ((nRead = stream.ReadByte()) != -1) lst.Add((byte)nRead);
byte[] byHtml = lst.ToArray();
//utf8的编码比较多 所以默认先用他解码
strHtml = Encoding.UTF8.GetString(byHtml, 0, byHtml.Length);
//就算编码没对也不会影响英文和数字的显示 然后匹配真正编码
string strCharSet =
Regex.Match(strHtml, @"<meta.*?charset=""?([a-z0-9-]+)\b", RegexOptions.IgnoreCase)
.Groups[1].Value;
//如果匹配到了标签并且不是utf8 那么重新解码一次
if (strCharSet != "" && (strCharSet.ToLower().IndexOf("utf") == -1)) {
try {
strHtml = Encoding.GetEncoding(strCharSet).GetString(byHtml, 0, byHtml.Length);
} catch { }
}
}
return strHtml;
}

在百度的时候 有说可以用httpWebRespones取出html的头 里面或许有编码 但是我试了好多 发现里面都没有 然后又不想去研究那些类的具体用法 所以就解析两次算了
[仅供参考]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: