网站优化
网站优化排名工具

什么是seo?SEO技术是什么?
SEO就是搜索引擎优化,SEO简单理解就是自然搜索结果获得网站排名与搜索流量的技术和过程。SEO技术是指在了解搜索引擎自然排名机制的基础上, 对网站进行内部及外部的调整优化, 改进网站在搜索引擎中的关键词自然排名, 获得更多搜索流量及目标客户转化率, 从而达到网站销售及品牌建设的目标。网站无排名,一切等于零,云优化专注中小企业网站排名优化服务,帮您您的网站快速提升关键词自然排名及客户转化!QQ:2852270685

SEO专题

C#如何获取百度指数?源码案例分析

本站来源:本站 发布时间:2013/6/4 20:33:35


由于百度指数是以Flash的形式在客户端展现出来的,不方便直接取到,开始我以为要用C#程序和Flash客户端交互。但按常理,我们需要分析发送客户度请求是发送到服务器的数据和返回的响应结果(其实基本所有的外挂都是这样做的)。

 

我使用的抓包工具是HTTP Analyzer,通过查看Post Data,可以看到客户端是发送了一个Post请求到http://index.baidu.com/gateway.php

发送的数据是一个AMF Message

那么我们需要研究下我们如何能让我们的程序发送出相同的请求。

再此之前我们需要了解下AMF的概念,AMF是Adobe公司开发的数据交互和远程过程调用的协议,全称为Action Message Format,很类似于WebService。但WebService传递的是XML文本数据,而AMF使用Http传输的是二进制数据。

AMF中主要使用的数据类型如下:


我们看下向服务器发送的AMF Message信息,HEX显示如下

这些二进制数据的分析如下
0003 说明使用的AMF版本,目前AMF有两个版本,0000 表示 AMF0,0003表示AMF3
0000 表示AMF Header的数量0
0001 表示AMF Body的数量1
0017 表示调用的方法的长度占23个字节(17的16进制就是23)
接下来
4461 7461 4163 6365 7373 6f72 2e67 6574 496e 6465 7865 73
这23个字节表示调用服务器端的方法是DataAccessor.getIndexes(44的16进制就是68,也就是D,后面不再做类似解释)
接下来的 00 022f 31 表示target作为标识实现请求和响应的联系,一般是自增整数。00表示数据类型为Number,02表示长度为两个字节,2f 31其实就是/1

00 0000 2d Body的长度为Number类型,长度为45

0a 0000 0003 0a表示数组类型(类似于C#中的Dictionary,键值对,键总是string类型),长度为3

数组的第一部分
0200 0ce5 a881 e8bf 85e6 9599 e882 b2 02表示字符串类型,0c表示此字符串长度为12,后面的e5 a881 e8bf 85e6 9599 e882 b2
表示传递的数据,可以用下段代码查看


数组的第二部分
02 0001 30 字符串0,不知道有什么意义

数组的第三部分
02 0012 3230 3130 2d36 2d31 7c32 3031 302d 362d 3131
长度为18的字符串,内容为2010-6-1|2010-6-11

至此,请求的数据我们已经分析完毕,再简单说下返回的数据(Response Content)


返回的AMF Message当然也包括Header和Body(数组类型)
Body的Target为/1/onResult
Body的Content包括
key String类型 就是我们传进去的关键词
area Number类型 0
areaName String类型 可以用上面的代码看到内容,就是全国
userIndexes String类型 这里都是百度指数(用户关注度),用逗号分隔开
mediaIndexes String类型 这里都是媒体指数(媒体关注度),用逗号分隔开(由于图中userIndexes 占位较多,所以未显示出来,在userIndexes数据下方)

如果想得到最后一天的百度指数,只要找到mediaIndexes前面最后一个逗号后跟的数字即可(当然要排除mediaIndexes本身数据类型及长度的占位字节)

前面我们已经分析了发送给服务器的数据,下面就是我们怎样把这些数据post到服务器了,我们看到对AMF的二进制数据处理(序列化及反序列化)很麻烦,有兴趣的朋友可以使

用FluroineFx
FluroineFx官方网站:
http://www.fluorinefx.com/   
FluroineFx下载地址:
http://www.fluorinefx.com/download.html
FluroineFx在线文档:
http://www.fluorinefx.com/docs/fluorine/index.html

但由于我们的应用非常简单,所以使用网上流传的一个模拟AMF Post的类,做了些修改,主要是我们现在应用的编码为UTF8

  1. class AMFPostData  
  2. {  
  3.     public List<byte> Message;  
  4.   
  5.     /// <summary>      
  6.     /// 初始化Message      
  7.     /// </summary>      
  8.     /// <param name="amftype"></param>      
  9.     /// <param name="headers"></param>      
  10.     /// <param name="bodies"></param>      
  11.     public AMFPostData(AMFType amftype, int headers, int bodies)  
  12.     {  
  13.         //AMF版本      
  14.         if (amftype == AMFType.AMF0)  
  15.         {  
  16.             Message = new List<byte>(new byte[] { 0x00, 0x00 });  
  17.         }  
  18.         else if (amftype == AMFType.AMF3)  
  19.         {  
  20.             Message = new List<byte>(new byte[] { 0x00, 0x03 });  
  21.         }  
  22.   
  23.         //header数量      
  24.         Message.Add(BitConverter.GetBytes(headers)[1]);  
  25.         Message.Add(BitConverter.GetBytes(headers)[0]);  
  26.         //body数量      
  27.         Message.Add(BitConverter.GetBytes(bodies)[1]);  
  28.         Message.Add(BitConverter.GetBytes(bodies)[0]);  
  29.     }  
  30.   
  31.     /// <summary>      
  32.     /// 添加Target      
  33.     /// </summary>      
  34.     /// <param name="target"></param>      
  35.     /// <param name="response"></param>      
  36.     public void AddTargetAndResponse(string target, string response)  
  37.     {  
  38.         //添加Target长度      
  39.         Message.Add(BitConverter.GetBytes(target.Length)[1]);  
  40.         Message.Add(BitConverter.GetBytes(target.Length)[0]);  
  41.         //添加Target内容      
  42.         Message.AddRange(Encoding.UTF8.GetBytes(target));  
  43.   
  44.         //添加Response长度      
  45.         Message.Add(BitConverter.GetBytes(response.Length)[1]);  
  46.         Message.Add(BitConverter.GetBytes(response.Length)[0]);  
  47.         //添加Response内容      
  48.         Message.AddRange(Encoding.UTF8.GetBytes(response));  
  49.     }  
  50.   
  51.     /// <summary>      
  52.     /// 添加Body      
  53.     /// </summary>      
  54.     /// <param name="length"></param>      
  55.     /// <param name="Content"></param>      
  56.     public void AddBody(AMFPostDataBody amfpostdatabody)  
  57.     {  
  58.         Message.AddRange(amfpostdatabody.GetLength());  
  59.         Message.AddRange(amfpostdatabody.Content.ToArray());  
  60.     }  
  61. }  
  62.   
  63. class AMFPostDataBody  
  64. {  
  65.     private byte[] length = new byte[4];  
  66.     public List<byte> Content = new List<byte>();  
  67.   
  68.     /// <summary>      
  69.     /// 初始化Body      
  70.     /// </summary>      
  71.     /// <param name="datatype"></param>      
  72.     /// <param name="arraylength"></param>      
  73.     public AMFPostDataBody(DataType datatype, int arraylength)  
  74.     {  
  75.         //添加类型标识      
  76.         Content.Add((byte)datatype);  
  77.   
  78.         //数组的话添加长度      
  79.         if (datatype == DataType.Array)  
  80.         {  
  81.             Content.Add(BitConverter.GetBytes(arraylength)[3]);  
  82.             Content.Add(BitConverter.GetBytes(arraylength)[2]);  
  83.             Content.Add(BitConverter.GetBytes(arraylength)[1]);  
  84.             Content.Add(BitConverter.GetBytes(arraylength)[0]);  
  85.         }  
  86.     }  
  87.   
  88.     public void AddData(DataType datatype, string value)  
  89.     {  
  90.         //添加类型标识      
  91.         Content.Add((byte)datatype);  
  92.   
  93.         switch (datatype)  
  94.         {  
  95.             case DataType.Number:  
  96.                 AddData(double.Parse(value));  
  97.                 break;  
  98.             case DataType.String:  
  99.                 AddData(value);  
  100.                 break;  
  101.             case DataType.Boolean:  
  102.                 AddData(Boolean.Parse(value));  
  103.                 break;  
  104.         }  
  105.     }  
  106.     #region 各种类型处理方法   
  107.     /// <summary>      
  108.     /// Boolean      
  109.     /// </summary>      
  110.     /// <param name="flag"></param>      
  111.     private void AddData(bool flag)  
  112.     {  
  113.         if (flag)  
  114.             Content.Add(0x01);  
  115.         else  
  116.             Content.Add(0x00);  
  117.     }  
  118.     /// <summary>      
  119.     /// String      
  120.     /// </summary>      
  121.     /// <param name="value"></param>      
  122.     private void AddData(string value)  
  123.     {  
  124.         //添加长度      
  125.         Content.Add(BitConverter.GetBytes(Encoding.UTF8.GetBytes(value).Length)[1]);  
  126.         Content.Add(BitConverter.GetBytes(Encoding.UTF8.GetBytes(value).Length)[0]);  
  127.         //添加内容      
  128.         Content.AddRange(Encoding.UTF8.GetBytes(value));  
  129.     }  
  130.     /// <summary>      
  131.     /// Number      
  132.     /// </summary>      
  133.     /// <param name="number"></param>      
  134.     private void AddData(double number)  
  135.     {  
  136.         byte[] b = new byte[8];  
  137.         b = BitConverter.GetBytes(number);  
  138.         for (int i = 7; i > -1; i--)  
  139.         {  
  140.             Content.Add(b[i]);  
  141.         }  
  142.     }  
  143.     #endregion   
  144.   
  145.     public byte[] GetLength()  
  146.     {  
  147.         length[0] = BitConverter.GetBytes(Content.Count)[3];  
  148.         length[1] = BitConverter.GetBytes(Content.Count)[2];  
  149.         length[2] = BitConverter.GetBytes(Content.Count)[1];  
  150.         length[3] = BitConverter.GetBytes(Content.Count)[0];  
  151.   
  152.         return length;  
  153.     }  
  154. }  
  155.   
  156. public enum AMFType  
  157. {  
  158.     AMF0,  
  159.     AMF3  
  160. }  
  161.   
  162. public enum DataType  
  163. {  
  164.     Number = 0,  
  165.     Boolean = 1,  
  166.     String = 2,  
  167.     UntypedObject = 3,  
  168.     MovieClip = 4,  
  169.     Null = 5,  
  170.     Undefined = 6,  
  171.     ReferencedObject = 7,  
  172.     MixedArray = 8,  
  173.     End = 9,  
  174.     Array = 10,//0x0A      
  175.     Date = 11,//0x0B      
  176.     LongString = 12,//0x0C      
  177.     TypeAsObject = 13,//0x0D      
  178.     Recordset = 14,//0x0E      
  179.     Xml = 15,//0x0F      
  180.     TypedObject = 16,//0x10      
  181.     AMF3data = 17//0x11      
  182. }  


根据前文分析结果,我们生成数据的方法如下


可以使用以下方法发送数据及得到返回响应的二进制数据

  1. public static byte[] GetFlashData(string gateway, byte[] data)  
  2. {  
  3.     HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(gateway);  
  4.     request.Method = "Post";  
  5.     request.ContentType = "application/x-amf";  
  6.     CookieContainer cookie = new CookieContainer();  
  7.     request.CookieContainer = cookie;  
  8.   
  9.     byte[] requestData = data;  
  10.     request.ContentLength = requestData.Length;  
  11.   
  12.     byte[] responseData = null;  
  13.   
  14.     try  
  15.     {  
  16.         using (Stream requestStream = request.GetRequestStream())  
  17.         {  
  18.             requestStream.Write(requestData, 0, requestData.Length);  
  19.         }  
  20.   
  21.         HttpWebResponse response = (HttpWebResponse)request.GetResponse();  
  22.         using (Stream responseStream = response.GetResponseStream())  
  23.         {  
  24.      //StreamToBytes是将流转换为二进制字节数组的方法,下文补上   
  25.             responseData = StreamToBytes(responseStream);  
  26.         }  
  27.     }  
  28.     catch (Exception ex)  
  29.     {  
  30.         Console.WriteLine(DateTime.Now.ToString() + "," + ex.Message);  
  31.         //Log.WriteLine(DateTime.Now.ToString() + "," + ex.Message);   
  32.     }  
  33.     return responseData;  
  34. }  

    由于返回的Stream只能Read,所以转换为二进制流麻烦一些,并且考虑到AMF中流结束的标记为00 00 09,所以写了如下方法得到返回的二进制流


    对返回数据的分析第一篇已经说过了,考虑到分析二进制数据比较麻烦,而实际上我们需要的数据就在userIndexes和mediaIndexes之间,所以我用了如下的方法返回最后7天的百度指数

    1. private static List<int> GetIndexs(byte[] data)  
    2. {  
    3.     if (data == null)  
    4.     {  
    5.         return null;  
    6.     }  
    7.     List<int> result = new List<int>();  
    8.     string str = Encoding.UTF8.GetString(data);  
    9.   
    10.     string start = "userIndexes";  
    11.     string end = "mediaIndexes";  
    12.     int startIndex = str.IndexOf(start) + start.Length;  
    13.     int endIndex = str.IndexOf(end);  
    14.   
    15.     string[] temp = str.Substring(startIndex, endIndex - startIndex).Split(',');  
    16.   
    17.     result.Add(StringToInt(temp[temp.Length - 1]));  
    18.   
    19.     int number = 0;  
    20.     for (int index = temp.Length - 2; index > temp.Length - 8; index--)  
    21.     {  
    22.         int.TryParse(temp[index], out number);  
    23.         result.Add(number);  
    24.     }  
    25.   
    26.     return result;  
    27.   
    28.     //以下为测试代码   
    29.     //int count = 0;   
    30.     //foreach (byte item in data)   
    31.     //{   
    32.     //    Log.Write(item.ToString("X2"));   
    33.     //    Log.Write(" ");   
    34.     //    count++;   
    35.     //    if (count == 16)   
    36.     //    {   
    37.     //        count = 0;   
    38.     //        Log.Write(System.Environment.NewLine);   
    39.     //    }   
    40.     //}   
    41. }  
    42. //最后一天的数据由于和mediaIndexes中有包含数据类型长度的字节,特殊处理下   
    43. public static int StringToInt(string str)  
    44. {  
    45.     int result = 0;  
    46.     int number = 0;  
    47.     for (int i = 0; i < str.Length; i++)  
    48.     {  
    49.         number = str[i] - '0';  
    50.         if (number >= 0 && number <= 9)  
    51.         {  
    52.             result = result * 10 + number;  
    53.         }  
    54.         else  
    55.         {  
    56.             break;  
    57.         }  
    58.     }  
    59.     return result;  
    60. }  


    下面是主函数的调用

由于百度指数是以Flash的形式在客户端展现出来的,不方便直接取到,开始我以为要用C#程序和Flash客户端交互。但按常理,我们需要分析发送客户度请求是发送到服务器的数据和返回的响应结果(其实基本所有的外挂都是这样做的)。

 

我使用的抓包工具是HTTP Analyzer,通过查看Post Data,可以看到客户端是发送了一个Post请求到http://index.baidu.com/gateway.php

发送的数据是一个AMF Message

那么我们需要研究下我们如何能让我们的程序发送出相同的请求。

再此之前我们需要了解下AMF的概念,AMF是Adobe公司开发的数据交互和远程过程调用的协议,全称为Action Message Format,很类似于WebService。但WebService传递的是XML文本数据,而AMF使用Http传输的是二进制数据。

AMF中主要使用的数据类型如下:


我们看下向服务器发送的AMF Message信息,HEX显示如下

这些二进制数据的分析如下
0003 说明使用的AMF版本,目前AMF有两个版本,0000 表示 AMF0,0003表示AMF3
0000 表示AMF Header的数量0
0001 表示AMF Body的数量1
0017 表示调用的方法的长度占23个字节(17的16进制就是23)
接下来
4461 7461 4163 6365 7373 6f72 2e67 6574 496e 6465 7865 73
这23个字节表示调用服务器端的方法是DataAccessor.getIndexes(44的16进制就是68,也就是D,后面不再做类似解释)
接下来的 00 022f 31 表示target作为标识实现请求和响应的联系,一般是自增整数。00表示数据类型为Number,02表示长度为两个字节,2f 31其实就是/1

00 0000 2d Body的长度为Number类型,长度为45

0a 0000 0003 0a表示数组类型(类似于C#中的Dictionary,键值对,键总是string类型),长度为3

数组的第一部分
0200 0ce5 a881 e8bf 85e6 9599 e882 b2 02表示字符串类型,0c表示此字符串长度为12,后面的e5 a881 e8bf 85e6 9599 e882 b2
表示传递的数据,可以用下段代码查看


数组的第二部分
02 0001 30 字符串0,不知道有什么意义

数组的第三部分
02 0012 3230 3130 2d36 2d31 7c32 3031 302d 362d 3131
长度为18的字符串,内容为2010-6-1|2010-6-11

至此,请求的数据我们已经分析完毕,再简单说下返回的数据(Response Content)


返回的AMF Message当然也包括Header和Body(数组类型)
Body的Target为/1/onResult
Body的Content包括
key String类型 就是我们传进去的关键词
area Number类型 0
areaName String类型 可以用上面的代码看到内容,就是全国
userIndexes String类型 这里都是百度指数(用户关注度),用逗号分隔开
mediaIndexes String类型 这里都是媒体指数(媒体关注度),用逗号分隔开(由于图中userIndexes 占位较多,所以未显示出来,在userIndexes数据下方)

如果想得到最后一天的百度指数,只要找到mediaIndexes前面最后一个逗号后跟的数字即可(当然要排除mediaIndexes本身数据类型及长度的占位字节)

前面我们已经分析了发送给服务器的数据,下面就是我们怎样把这些数据post到服务器了,我们看到对AMF的二进制数据处理(序列化及反序列化)很麻烦,有兴趣的朋友可以使

用FluroineFx
FluroineFx官方网站:
http://www.fluorinefx.com/   
FluroineFx下载地址:
http://www.fluorinefx.com/download.html
FluroineFx在线文档:
http://www.fluorinefx.com/docs/fluorine/index.html

但由于我们的应用非常简单,所以使用网上流传的一个模拟AMF Post的类,做了些修改,主要是我们现在应用的编码为UTF8

  1. class AMFPostData  
  2. {  
  3.     public List<byte> Message;  
  4.   
  5.     /// <summary>      
  6.     /// 初始化Message      
  7.     /// </summary>      
  8.     /// <param name="amftype"></param>      
  9.     /// <param name="headers"></param>      
  10.     /// <param name="bodies"></param>      
  11.     public AMFPostData(AMFType amftype, int headers, int bodies)  
  12.     {  
  13.         //AMF版本      
  14.         if (amftype == AMFType.AMF0)  
  15.         {  
  16.             Message = new List<byte>(new byte[] { 0x00, 0x00 });  
  17.         }  
  18.         else if (amftype == AMFType.AMF3)  
  19.         {  
  20.             Message = new List<byte>(new byte[] { 0x00, 0x03 });  
  21.         }  
  22.   
  23.         //header数量      
  24.         Message.Add(BitConverter.GetBytes(headers)[1]);  
  25.         Message.Add(BitConverter.GetBytes(headers)[0]);  
  26.         //body数量      
  27.         Message.Add(BitConverter.GetBytes(bodies)[1]);  
  28.         Message.Add(BitConverter.GetBytes(bodies)[0]);  
  29.     }  
  30.   
  31.     /// <summary>      
  32.     /// 添加Target      
  33.     /// </summary>      
  34.     /// <param name="target"></param>      
  35.     /// <param name="response"></param>      
  36.     public void AddTargetAndResponse(string target, string response)  
  37.     {  
  38.         //添加Target长度      
  39.         Message.Add(BitConverter.GetBytes(target.Length)[1]);  
  40.         Message.Add(BitConverter.GetBytes(target.Length)[0]);  
  41.         //添加Target内容      
  42.         Message.AddRange(Encoding.UTF8.GetBytes(target));  
  43.   
  44.         //添加Response长度      
  45.         Message.Add(BitConverter.GetBytes(response.Length)[1]);  
  46.         Message.Add(BitConverter.GetBytes(response.Length)[0]);  
  47.         //添加Response内容      
  48.         Message.AddRange(Encoding.UTF8.GetBytes(response));  
  49.     }  
  50.   
  51.     /// <summary>      
  52.     /// 添加Body      
  53.     /// </summary>      
  54.     /// <param name="length"></param>      
  55.     /// <param name="Content"></param>      
  56.     public void AddBody(AMFPostDataBody amfpostdatabody)  
  57.     {  
  58.         Message.AddRange(amfpostdatabody.GetLength());  
  59.         Message.AddRange(amfpostdatabody.Content.ToArray());  
  60.     }  
  61. }  
  62.   
  63. class AMFPostDataBody  
  64. {  
  65.     private byte[] length = new byte[4];  
  66.     public List<byte> Content = new List<byte>();  
  67.   
  68.     /// <summary>      
  69.     /// 初始化Body      
  70.     /// </summary>      
  71.     /// <param name="datatype"></param>      
  72.     /// <param name="arraylength"></param>      
  73.     public AMFPostDataBody(DataType datatype, int arraylength)  
  74.     {  
  75.         //添加类型标识      
  76.         Content.Add((byte)datatype);  
  77.   
  78.         //数组的话添加长度      
  79.         if (datatype == DataType.Array)  
  80.         {  
  81.             Content.Add(BitConverter.GetBytes(arraylength)[3]);  
  82.             Content.Add(BitConverter.GetBytes(arraylength)[2]);  
  83.             Content.Add(BitConverter.GetBytes(arraylength)[1]);  
  84.             Content.Add(BitConverter.GetBytes(arraylength)[0]);  
  85.         }  
  86.     }  
  87.   
  88.     public void AddData(DataType datatype, string value)  
  89.     {  
  90.         //添加类型标识      
  91.         Content.Add((byte)datatype);  
  92.   
  93.         switch (datatype)  
  94.         {  
  95.             case DataType.Number:  
  96.                 AddData(double.Parse(value));  
  97.                 break;  
  98.             case DataType.String:  
  99.                 AddData(value);  
  100.                 break;  
  101.             case DataType.Boolean:  
  102.                 AddData(Boolean.Parse(value));  
  103.                 break;  
  104.         }  
  105.     }  
  106.     #region 各种类型处理方法   
  107.     /// <summary>      
  108.     /// Boolean      
  109.     /// </summary>      
  110.     /// <param name="flag"></param>      
  111.     private void AddData(bool flag)  
  112.     {  
  113.         if (flag)  
  114.             Content.Add(0x01);  
  115.         else  
  116.             Content.Add(0x00);  
  117.     }  
  118.     /// <summary>      
  119.     /// String      
  120.     /// </summary>      
  121.     /// <param name="value"></param>      
  122.     private void AddData(string value)  
  123.     {  
  124.         //添加长度      
  125.         Content.Add(BitConverter.GetBytes(Encoding.UTF8.GetBytes(value).Length)[1]);  
  126.         Content.Add(BitConverter.GetBytes(Encoding.UTF8.GetBytes(value).Length)[0]);  
  127.         //添加内容      
  128.         Content.AddRange(Encoding.UTF8.GetBytes(value));  
  129.     }  
  130.     /// <summary>      
  131.     /// Number      
  132.     /// </summary>      
  133.     /// <param name="number"></param>      
  134.     private void AddData(double number)  
  135.     {  
  136.         byte[] b = new byte[8];  
  137.         b = BitConverter.GetBytes(number);  
  138.         for (int i = 7; i > -1; i--)  
  139.         {  
  140.             Content.Add(b[i]);  
  141.         }  
  142.     }  
  143.     #endregion   
  144.   
  145.     public byte[] GetLength()  
  146.     {  
  147.         length[0] = BitConverter.GetBytes(Content.Count)[3];  
  148.         length[1] = BitConverter.GetBytes(Content.Count)[2];  
  149.         length[2] = BitConverter.GetBytes(Content.Count)[1];  
  150.         length[3] = BitConverter.GetBytes(Content.Count)[0];  
  151.   
  152.         return length;  
  153.     }  
  154. }  
  155.   
  156. public enum AMFType  
  157. {  
  158.     AMF0,  
  159.     AMF3  
  160. }  
  161.   
  162. public enum DataType  
  163. {  
  164.     Number = 0,  
  165.     Boolean = 1,  
  166.     String = 2,  
  167.     UntypedObject = 3,  
  168.     MovieClip = 4,  
  169.     Null = 5,  
  170.     Undefined = 6,  
  171.     ReferencedObject = 7,  
  172.     MixedArray = 8,  
  173.     End = 9,  
  174.     Array = 10,//0x0A      
  175.     Date = 11,//0x0B      
  176.     LongString = 12,//0x0C      
  177.     TypeAsObject = 13,//0x0D      
  178.     Recordset = 14,//0x0E      
  179.     Xml = 15,//0x0F      
  180.     TypedObject = 16,//0x10      
  181.     AMF3data = 17//0x11      
  182. }  


根据前文分析结果,我们生成数据的方法如下


可以使用以下方法发送数据及得到返回响应的二进制数据

  1. public static byte[] GetFlashData(string gateway, byte[] data)  
  2. {  
  3.     HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(gateway);  
  4.     request.Method = "Post";  
  5.     request.ContentType = "application/x-amf";  
  6.     CookieContainer cookie = new CookieContainer();  
  7.     request.CookieContainer = cookie;  
  8.   
  9.     byte[] requestData = data;  
  10.     request.ContentLength = requestData.Length;  
  11.   
  12.     byte[] responseData = null;  
  13.   
  14.     try  
  15.     {  
  16.         using (Stream requestStream = request.GetRequestStream())  
  17.         {  
  18.             requestStream.Write(requestData, 0, requestData.Length);  
  19.         }  
  20.   
  21.         HttpWebResponse response = (HttpWebResponse)request.GetResponse();  
  22.         using (Stream responseStream = response.GetResponseStream())  
  23.         {  
  24.      //StreamToBytes是将流转换为二进制字节数组的方法,下文补上   
  25.             responseData = StreamToBytes(responseStream);  
  26.         }  
  27.     }  
  28.     catch (Exception ex)  
  29.     {  
  30.         Console.WriteLine(DateTime.Now.ToString() + "," + ex.Message);  
  31.         //Log.WriteLine(DateTime.Now.ToString() + "," + ex.Message);   
  32.     }  
  33.     return responseData;  
  34. }  

    由于返回的Stream只能Read,所以转换为二进制流麻烦一些,并且考虑到AMF中流结束的标记为00 00 09,所以写了如下方法得到返回的二进制流


    对返回数据的分析第一篇已经说过了,考虑到分析二进制数据比较麻烦,而实际上我们需要的数据就在userIndexes和mediaIndexes之间,所以我用了如下的方法返回最后7天的百度指数

    1. private static List<int> GetIndexs(byte[] data)  
    2. {  
    3.     if (data == null)  
    4.     {  
    5.         return null;  
    6.     }  
    7.     List<int> result = new List<int>();  
    8.     string str = Encoding.UTF8.GetString(data);  
    9.   
    10.     string start = "userIndexes";  
    11.     string end = "mediaIndexes";  
    12.     int startIndex = str.IndexOf(start) + start.Length;  
    13.     int endIndex = str.IndexOf(end);  
    14.   
    15.     string[] temp = str.Substring(startIndex, endIndex - startIndex).Split(',');  
    16.   
    17.     result.Add(StringToInt(temp[temp.Length - 1]));  
    18.   
    19.     int number = 0;  
    20.     for (int index = temp.Length - 2; index > temp.Length - 8; index--)  
    21.     {  
    22.         int.TryParse(temp[index], out number);  
    23.         result.Add(number);  
    24.     }  
    25.   
    26.     return result;  
    27.   
    28.     //以下为测试代码   
    29.     //int count = 0;   
    30.     //foreach (byte item in data)   
    31.     //{   
    32.     //    Log.Write(item.ToString("X2"));   
    33.     //    Log.Write(" ");   
    34.     //    count++;   
    35.     //    if (count == 16)   
    36.     //    {   
    37.     //        count = 0;   
    38.     //        Log.Write(System.Environment.NewLine);   
    39.     //    }   
    40.     //}   
    41. }  
    42. //最后一天的数据由于和mediaIndexes中有包含数据类型长度的字节,特殊处理下   
    43. public static int StringToInt(string str)  
    44. {  
    45.     int result = 0;  
    46.     int number = 0;  
    47.     for (int i = 0; i < str.Length; i++)  
    48.     {  
    49.         number = str[i] - '0';  
    50.         if (number >= 0 && number <= 9)  
    51.         {  
    52.             result = result * 10 + number;  
    53.         }  
    54.         else  
    55.         {  
    56.             break;  
    57.         }  
    58.     }  
    59.     return result;  
    60. }  


    下面是主函数的调用

seo服务

网站符合seo优化吗?关键词定位合理吗?网站体验友好吗?来访客户持续吗?客户留存率高吗?你有专业seo技术吗? seo优化