找回密码
 立即注册
查看: 1201|回复: 8

C#完整的获取网页内容 (考虑编码GZIP问题)

[复制链接]

936

回帖

7277

基友

7903

积分

会飞的醉颜

会飞的醉颜。

Rank: 13Rank: 13Rank: 13Rank: 13

二货勋章

发表于 2013-2-25 16:57:01 | 显示全部楼层 |阅读模式

之前看了很多获取网页源码的写法,要么有乱码,要么没考虑到gzip等压缩,比如有些网页这个HttpWebResponse 对象的CharacterSet是iso-8859-1,那么这种情况

我们根据它的charset读取。

   还有个将流转成byte[] 数组的。。。发现GetResponseStream() 的流不能获取length属性

   以下是全部源码

  1.         /// <summary>
  2.         /// 将 Stream 转成 byte[]
  3.         /// </summary>
  4.         private static byte[] StreamToBytes(Stream stream)
  5.         {
  6.             MemoryStream stmMemory = new MemoryStream();
  7.             byte[] buffer = new byte[4096];
  8.             int i;
  9.             while ((i = stream.Read(buffer, 0, buffer.Length)) > 0)
  10.             {
  11.                 stmMemory.Write(buffer, 0, i);
  12.             }
  13.             byte[] arraryByte = stmMemory.ToArray();
  14.             stmMemory.Close();


  15.             // 设置当前流的位置为流的开始
  16.             if (stream.CanSeek)
  17.             {
  18.                 stream.Seek(0, SeekOrigin.Begin);
  19.             }
  20.             return arraryByte;
  21.         }
  22.         /**  
  23. * 用getBytes(encoding):返回字符串的一个byte数组  
  24. * 当b[0]为 63时,应该是转码错误  
  25. * A、不乱码的汉字字符串:  
  26. * 1、encoding用GB2312时,每byte是负数;  
  27. * 2、encoding用ISO8859_1时,b[i]全是63。  
  28. * B、乱码的汉字字符串:  
  29. * 1、encoding用ISO8859_1时,每byte也是负数;  
  30. * 2、encoding用GB2312时,b[i]大部分是63。  
  31. * C、英文字符串  
  32. * 1、encoding用ISO8859_1和GB2312时,每byte都大于0;  
  33. * <p/>  
  34. * 总结:给定一个字符串,用getBytes("iso8859_1")  
  35. * 1、如果b[i]有63,不用转码; A-2  
  36. * 2、如果b[i]全大于0,那么为英文字符串,不用转码; B-1  
  37. * 3、如果b[i]有小于0的,那么已经乱码,要转码。 C-1  
  38. */
  39.         /// <summary>
  40.         /// //url是要访问的网站地址,charSet是目标网页的编码,如果传入的是null或者"",那就自动分析网页的编码
  41.         /// </summary>
  42.         /// <param name="url"></param>
  43.         /// <returns></returns>
  44.         public static string DoGet(string url, string charSet = null, string aspnetSessionID = null)
  45.         {
  46.             HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
  47.             if (!String.IsNullOrEmpty(aspnetSessionID))
  48.             {
  49.                 CookieContainer cookies = new CookieContainer();
  50.                 req.CookieContainer = cookies;
  51.                 Cookie appCookie = new Cookie("ASP.NET_SessionId", aspnetSessionID);//注意ASP.NET验证sessionID的名:ASP.NET_SessionId   
  52.                 req.CookieContainer.Add(new Uri(url), appCookie);
  53.             }
  54.             // 需要注意的:
  55.             //有的网页可能下不下来,有种种原因比如需要cookie,编码问题等等
  56.             //这是就要具体问题具体分析比如在头部加入cookie
  57.             // req.Headers.Add("Cookie", cookie);
  58.             //这样可能需要一些重载方法。根据需要写就可以了

  59.             //获取或设置用于对向 Internet 资源的请求进行身份验证的网络凭据。
  60.             req.Credentials = CredentialCache.DefaultCredentials;
  61.             //如果服务器要验证用户名,密码
  62.             //NetworkCredential mycred = new NetworkCredential(struser, strpassword);
  63.             //myWebClient.Credentials = mycred;
  64.             //从资源下载数据并返回字节数组。(加@是因为网址中间有"/"符号)

  65.             req.Method = "GET";
  66.             req.ContentType = "application/x-www-form-urlencoded";
  67.             HttpWebResponse res = (HttpWebResponse)req.GetResponse();
  68.             Stream receiveStream = res.GetResponseStream();
  69.             if (res.ContentEncoding.ToLower().Contains("gzip"))
  70.             {
  71.                 receiveStream = new GZipStream(receiveStream, CompressionMode.Decompress);
  72.             }
  73.             else
  74.                 if (res.ContentEncoding.ToLower().Contains("deflate"))
  75.                 {
  76.                     receiveStream = new DeflateStream(receiveStream, CompressionMode.Decompress);
  77.                 }

  78.             //获取网页字符编码描述信息
  79.             //Match charSetMatch = Regex.Match(strWebData, "<meta([^<]*)charset=([^<]*)"", RegexOptions.IgnoreCase | RegexOptions.Multiline);
  80.             //string webCharSet = charSetMatch.Groups[2].Value.Trim('"');
  81.             byte[] buffer = StreamToBytes(receiveStream);
  82.             Encoding encode = Encoding.UTF8;
  83.             if (String.IsNullOrEmpty(charSet))
  84.             {
  85.                 if (res.CharacterSet != null && res.CharacterSet != "" && (res.CharacterSet.ToLower() == "gbk" || res.CharacterSet.ToLower() == "gb2312"))
  86.                 {
  87.                     encode = Encoding.GetEncoding("gb2312");
  88.                 }
  89.             }
  90.             else
  91.             {
  92.                 encode = Encoding.GetEncoding(charSet);
  93.             }

  94.             string result = encode.GetString(buffer);

  95.             if (res.CharacterSet.ToLower() == "iso-8859-1")
  96.             {
  97.                 Match charSetMatch = Regex.Match(result, "<meta([^<]*)charset=([^<]*)"", RegexOptions.IgnoreCase | RegexOptions.Multiline);
  98.                 if (charSetMatch.Success)
  99.                 {
  100.                     string webCharSet = charSetMatch.Groups[2].Value.Trim('"');
  101.                     if (Encoding.GetEncoding(webCharSet) != encode)
  102.                     {
  103.                         result = Encoding.GetEncoding(webCharSet).GetString(buffer);
  104.                     }
  105.                 }
  106.             }

  107.             receiveStream.Close();
  108.             buffer = null;
  109.             return result;
  110.         }
复制代码
[size=1em]



回复

使用道具 举报

7657

回帖

86万

基友

34万

积分

天下一番

Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

伯爵荣耀

发表于 2013-2-25 17:26:15 | 显示全部楼层
我发现我的代码要比这个短好多  所以执行效率也高好多= =
回复 支持 反对

使用道具 举报

936

回帖

7277

基友

7903

积分

会飞的醉颜

会飞的醉颜。

Rank: 13Rank: 13Rank: 13Rank: 13

二货勋章

 楼主| 发表于 2013-2-25 17:27:40 | 显示全部楼层
飞龙 发表于 2013-2-25 17:26
我发现我的代码要比这个短好多  所以执行效率也高好多= =

= =这个比较好理解
回复 支持 反对

使用道具 举报

7657

回帖

86万

基友

34万

积分

天下一番

Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

伯爵荣耀

发表于 2013-2-25 17:36:51 | 显示全部楼层
醉颜儿 发表于 2013-2-25 17:27
= =这个比较好理解

而且我记得stream到byte[] 不是只要用.toarray()就行了么= =
回复 支持 反对

使用道具 举报

201

回帖

2514

基友

1300

积分

通神3段 Lv.6

Rank: 3Rank: 3

伯爵荣耀

发表于 2013-3-17 15:53:06 | 显示全部楼层
我要给你回复  
回复 支持 反对

使用道具 举报

201

回帖

2514

基友

1300

积分

通神3段 Lv.6

Rank: 3Rank: 3

伯爵荣耀

发表于 2013-3-17 15:54:04 | 显示全部楼层
我要升级啊给你回复  
回复 支持 反对

使用道具 举报

201

回帖

2514

基友

1300

积分

通神3段 Lv.6

Rank: 3Rank: 3

伯爵荣耀

发表于 2013-3-17 15:54:36 | 显示全部楼层
你们这些无聊的人呢   
回复 支持 反对

使用道具 举报

201

回帖

2514

基友

1300

积分

通神3段 Lv.6

Rank: 3Rank: 3

伯爵荣耀

发表于 2013-3-17 15:55:13 | 显示全部楼层
im好啊哈   啊啊啊啊啊
回复 支持 反对

使用道具 举报

163

回帖

121

基友

778

积分

通神2段 Lv.5

Rank: 3Rank: 3

发表于 2013-4-9 10:30:48 | 显示全部楼层
反正我又看不懂
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|苍海国际 ( 鲁ICP备13020644号-1 )

GMT+8, 2024-12-27 08:22 , Processed in 0.049326 second(s), 23 queries .

Powered by Discuz! Theme By eRic Modified by 4bpa

© CangHai International We Do Our Rights!

返回顶部