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

来源:互联网 发布:imf数据库使用指南 编辑:程序博客网 时间:2024/05/17 08:15

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的头 里面或许有编码 但是我试了好多 发现里面都没有 然后又不想去研究那些类的具体用法 所以就解析两次算了

[仅供参考]

0 0
原创粉丝点击