无尽的任务1-仿CNZZ的流量统计,完成80%(更新1次)

终于到周末了 ,任务也快接近尾声了,这次要写的流量统计,其实思路很简单,只是一些细节问题花掉了不少时间,对于采集各个浏览器的得到的关健词的乱码问题花的时间最多,换了几种思路。

现在先来简单介绍一下,任务背景和实现思路;手头有2000+个站点,一部分是使用了CNZZ的流量统计,由于CNZZ的流量统计,针对每一个站点要一个独立的账号来管理,所以所有的都采用CNZZ的流量统计,光注册账号都是个问题 ,所以老大给了个任务,要自己弄一个念CNZZ的流量统计出来, 不需要那么专业,目前现在只做数据采集,数据分析暂时不做,所以现在有的功能就是 从各个站点上,采集到数据然后插入到数据库中就行了。对数据分析这一块,现在用了公司之前写的c/s模式的软件替代先。由于只做采集,也急着用所以就用最简的方式写的。

要采集的信息:siteDomain 站点域名, siteRootDomain 站点根域, referer 来源页面, landingpage 访问页面, visittime 访问时间,keyword 关词词, searchengine 搜索引擎, browser 浏览器, os 操作系统, screenWidth 屏幕宽高比, ip IP地址, location 地区信息,reload 是否是F5刷新采集的。

当拿到任务时,直接在后台用 context.Request.。。。。就直接取到了 ,然后马上就交给老大了,直接被老大打回来了,他说不是要采集本站的,而采集手上2000多个站点上的访问的信息。 对于.NET提供的取来源页面针对本部做流量统计很好用 ,但是要用来采集,其它站的访问信息就做不到了。最后换下的思路是这样的。

写一个JS页面:在这个JS代码页中,使用document.referrer,document.location,screen.width,screen.height 取到访问页的来源页面,本页面,屏幕宽高比(分析来源页面中各个搜索引擎的关键词参数,抓取关键词,最后由于编码问题,关键词的分析统一放到后台去处理了),

再使用var code="<"+"script src='http://localhost:2195/TotalDEMO/StatisticsHandler.ashx?urlreferrer="+urlreferrer+"&locationurl="+locationurl+"&screenwidth="+screenwidth+"&screenheight="+screenheight+"'></"+"script>";
alert(urlreferrer);
document.write(code);

将js代码输出到,引用这个JS代码的页面中。

当访问引用了这段JS代码的页面时就会将这些信息采集放到后台去处理;对于地区信息的分析,是采用了纯真IP数库.dat文件,进行分析出来的。

对于要进行数据采集的页面只要在页面上加入<script type="text/javascript" src="http://localhost:2195/TotalDEMO/Statistics_new.js"></script>

 

现在先将主要的代码信息分享出来,由于目前还是测试中,还有很多没注意的地方。发现问题的朋友请告诉我一下,万分感谢。

JS页面代码(statistics.js):

 1 var urlreferrer = document.referrer;urlreferrer="http://www.baidu.com/s?wd=ihj%B5%C4%B5%C4%CA%C7&rsv_bp=0&rsv_spt=3&inputT=166822";
 2 //urlreferrer="http://www.baidu.com/baidu?tn=monline_5_dg&ie=utf-8&wd=%E5%9B%B4%E6%A3%8B%E7%83%ADss";
 3 if(urlreferrer=="")
 4 {
 5     urlreferrer="normal";
 6 } 
 7 
 8 urlreferrer= escape(urlreferrer);
 9 var locationurl = document.location;
10 locationurl= escape(locationurl);
11 var screenwidth = screen.width;
12 var screenheight = screen.height;
13 var code="<"+"script src='http://localhost:2195/TotalDEMO/StatisticsHandler.ashx?urlreferrer="+urlreferrer+"&locationurl="+locationurl+"&screenwidth="+screenwidth+"&screenheight="+screenheight+"&isrelod="+isreload+"'></"+"script>";
14 
15 document.write(code);

后台处理信息C#代码:

  1 using System;
  2 using System.Web;
  3 using System.Data;
  4 using System.Data.SqlClient;
  5 using System.Collections.Generic;
  6 using System.Text.RegularExpressions;
  7 using System.Text;
  8 
  9 
 10 
 11 public class StatisticsHandler : IHttpHandler {
 12     
 13     public void ProcessRequest (HttpContext context) {
 14         context.Response.ContentType = "text/plain";
 15                
 16         int reload = 0;                             //是否是刷新过来的,0否,1是
 17         int siteID = 0;                             //站点ID
 18         string referer;                             //来源页面
 19         string landingpage;                         //访问页面
 20         string siteDomain;                          //域名
 21         string siteRootDomain;                      //根域
 22         string visittime2;                          //访问时间
 23         int s_year;                                 //
 24         int s_month;                                //
 25         int s_day;                                  //
 26         int s_hour;                                 //小时
 27         string s_week="";                           //星期(EN)
 28         int week;                                   //星期(DI)
 29         string keyword;                             //关键词
 30         string searchengine;                        //搜索引擎
 31         string browser;                             //浏览器
 32         string screen;                              //屏幕宽高比
 33         string ip;                                  //IP地址
 34         string os;                                  //操作系统        
 35         string guid;                                //GUID 
 36         string location;                            //总地区信息
 37         string _errmsg;                             //地区错误信息       
 38         string formads;                             //来自页面    保留字段
 39         string country="中国";                      //国家
 40         string province;                            //省份
 41         string city;                                //城市
 42         //string area;                             //区          保留字段
 43         //string isp;                               //网络接入    保留字段
 44         GetFieldValue(context, out referer, out landingpage, out siteDomain, out siteRootDomain, out visittime2, out s_year, out s_month, out s_day, out s_hour, out s_week, out keyword, out searchengine, out browser, out screen, out ip, out os, out guid, out reload);
 45         week = SweekToIweek(s_week);
 46         ConventIPToArea(ip, out location, out _errmsg); //将IP转换成地区信息的方法
 47         if (!string.IsNullOrEmpty(_errmsg))             //当ip转换出现错误时地区信息填写错误信息
 48         {
 49             location = _errmsg;
 50         }
 51         
 52         Location _arelocal = new Location(location);    //城市信息类,用来拆分地区中包含的城市信息
 53         province = _arelocal.Captical;
 54         city = _arelocal.City;
 55         if (string.IsNullOrEmpty(province))             
 56         {
 57             country = string.Empty;                     //国家默认为中国,当省分为空的时间,国家信息留空
 58         }
 59 
 60        
 61         string sqltext = "insert into sts_track( siteID, siteDomain, siteRootDomain, referer, landingpage, visittime, [year], [month], [day], hour, week, keyword, searchengine, browser, os, screenWidth, ip, location,country, province, city, guid,reload) values(@siteID, @siteDomain, @siteRootDomain, @referer, @landingpage, @visittime, @year, @month, @day, @hour, @week, @keyword, @searchengine, @browser, @os, @screenWidth, @ip, @location,@country,@province,@city,@guid,@reload)";
 62       
 63         SqlParameter[] sqlpar = {
 64                                     new SqlParameter("@siteID",siteID),
 65                                     new SqlParameter("@siteDomain",siteDomain),
 66                                     new SqlParameter("@siteRootDomain",siteRootDomain),
 67                                     new SqlParameter("@referer",referer),
 68                                     new SqlParameter("@landingpage",landingpage),
 69                                     new SqlParameter("@visittime",visittime2),
 70                                     new SqlParameter("@year",s_year),
 71                                     new SqlParameter("@month",s_month),
 72                                     new SqlParameter("@day",s_day),
 73                                     new SqlParameter("@hour",s_hour),
 74                                     new SqlParameter("@week",week),
 75                                     new SqlParameter("@keyword",keyword),
 76                                     new SqlParameter("@searchengine",searchengine),
 77                                     new SqlParameter("@browser",browser),
 78                                     new SqlParameter("@os",os),
 79                                     new SqlParameter("@screenWidth",screen),
 80                                     new SqlParameter("@ip",ip),
 81                                     new SqlParameter("@location",location),
 82                                     new SqlParameter("@country",country),
 83                                     new SqlParameter("@province",province),
 84                                     new SqlParameter("@city",city),
 85                                     new SqlParameter("@guid",guid),
 86                                     new SqlParameter("@reload",reload)
 87                                 };
 88         int flag2= DB.ExecuteSql(sqltext, sqlpar);
 89         WriteCookie(context,"GUID",guid);
 90         context.Response.Write("");
 91      
 92     }
 93 
 94     /// <summary>
 95     /// 向浏览器端写入Cookie
 96     /// </summary>
 97     private void WriteCookie(HttpContext context,string key, string vlaue)
 98     {
 99         string cookiename = key;
100         HttpCookie cookie = new HttpCookie(cookiename);
101         cookie.Value = vlaue;
102         cookie.Expires = DateTime.Now.AddDays(30);
103         context.Response.Cookies.Set(cookie);
104         
105     }
106     /// <summary>
107     /// 读取cookie
108     /// </summary>    
109     private string ReadCookie(HttpContext context, string key)
110     {
111         try
112         {
113             HttpCookie cookie = context.Request.Cookies[key];
114             return cookie.Value; 
115         }
116         catch (Exception)
117         {
118 
119             return "";
120         }
121        
122     }
123 
124     /// <summary>
125     /// 此方法把IP地址转化为地区信息
126     /// </summary>
127     /// <param name="ip">ip地址</param>
128     /// <param name="Location">地区信息</param>
129     /// <param name="Errmsg">错误信息</param>
130     private void ConventIPToArea(string ip, out string Location, out string Errmsg)
131     {
132         IPScaner ipscaner = new IPScaner();         //转化IP的类
133         ipscaner.DataPath = HttpContext.Current.Server.MapPath("~/App_Data/CoralWry.dat");  //连接纯真数据文件的地址属性
134         ipscaner.IP = ip;
135         Location = ipscaner.IPLocation();          //地区总信息 国家+地区 格式    
136         Errmsg = ipscaner.ErrMsg;                  //IP转换出错时信息
137          
138     }
139     
140     
141     
142     /// <summary>
143     /// 此方法将星期转换成数字表示
144     /// </summary>
145     /// <param name="weekstr">星期英文表示(自动生成)</param>
146     /// <returns></returns>
147     private int SweekToIweek(string weekstr)
148     {
149         int Iweek = 0;
150         switch (weekstr)
151         {
152             case "Monday": Iweek = 1; break;
153             case "Tuesday": Iweek = 2; break;
154             case "Wednesday": Iweek = 3; break;
155             case "Thursday": Iweek = 4; break;
156             case "Friday": Iweek = 5; break;
157             case "Saturday": Iweek = 6; break;
158             case "Sunday": Iweek = 7; break;
159             default: Iweek = 0; break;
160         }
161         return Iweek;
162     } 
163     
164     
165     /// <summary>
166     /// 此方法用来初始各字段的值,提取出来的方法;
167     /// </summary>   
168     private void GetFieldValue(HttpContext context, out string referer, out string landingpage, out string siteDomain, out string siteRootDomain, out string visittime2, out int s_year, out int s_month, out int s_day, out int s_hour, out string s_week, out string keyword, out string searchengine, out string browser, out string screen, out string ip, out string os, out string guid, out int reload)
169     {
170         string isreload = context.Request.QueryString["isrelod"];
171         reload = Convert.ToInt32(isreload);        
172         referer = context.Request.QueryString["urlreferrer"];                //页面来源       
173         landingpage = context.Request.QueryString["locationurl"];            //访问页面
174         try
175         {
176             Uri landingpageuri = new Uri(landingpage);                       //将页面字符串URL转成C#URI类
177             siteDomain = landingpageuri.DnsSafeHost;                         //站点域名
178             siteRootDomain = landingpageuri.DnsSafeHost;                     //站点根域
179             int dotindex = siteRootDomain.IndexOf('.');
180             if (dotindex != -1)
181             {
182                 siteRootDomain = siteRootDomain.Substring(dotindex + 1);
183             }
184 
185         }
186         catch (Exception)
187         {
188             siteDomain = "";                                                //站点域名
189             siteRootDomain = "";                                            //站点根域
190 
191         }
192         
193        
194 
195         DateTime visittime = context.Timestamp;                              //访问时间-用来拆分时间的年月日等等
196         visittime2 = visittime.ToString();                                   //访问时间用来直接插入
197         s_year = visittime.Year;                                             //
198         s_month = visittime.Month;                                           //
199         s_day = visittime.Day;                                               //
200         s_hour = visittime.Hour;                                             //小时
201         s_week = visittime.DayOfWeek.ToString();                             //星期
202        
203 
204         keyword = GetKeyWord(referer);                                       //关键词
205 
206         try
207         {
208             Uri referurl = new Uri(referer);                                     //搜索引擎 即为页面来源的域名
209             searchengine = FromSearchengine(referurl.DnsSafeHost);               //搜索引擎
210         }
211         catch (Exception)
212         {
213             searchengine = "";                                                   //搜索引擎
214            
215         }
216             
217        
218         browser = context.Request.Browser.Browser;                           //浏览器版本
219         string screenwidth = context.Request.QueryString["screenwidth"];     //屏幕宽度
220         string screenheight = context.Request.QueryString["screenheight"];   //屏幕高度
221         screen = screenwidth + "*" + screenheight;                           //屏幕宽高比
222         ip = context.Request.UserHostAddress;                                //远程IP
223         os = context.Request.Browser.Platform;                               //操作系统 
224         
225         string haveGUID = ReadCookie(context,"GUID");                        //从cookie中取GUID如果有则不分配新的GUID
226         if (string.IsNullOrEmpty(haveGUID))                                
227         {
228             guid = Guid.NewGuid().ToString("N");                             //GUID 标识
229         }
230         else 
231         {
232             guid = haveGUID;
233         }
234     }
235 
236 
237 
238     /// <summary>
239     /// 获取搜索关键词
240     /// </summary>
241     /// <param name="url">来源地址</param>
242     /// <returns></returns>
243     private string GetKeyWord(string url)
244     {
245         string keyword = "";
246         string[] _uOsr = { "google", "yahoo", "baidu", "soso", "bing", "sogou" };   //将几个搜索引擎与对应的搜索关系词写入对应的数组中
247         string[] _uOkw = { "q", "q", "wd|word", "w", "q", "query" };
248         for (int i = 0; i < _uOsr.Length; i++)
249         {
250             if (url.Contains(_uOsr[i]))                                             //如果URL中包含这几个搜索引擎则进入处理
251             {
252                 if (_uOsr[i] == "baidu")
253                 {
254                     string[] temp = _uOkw[i].Split('|');                            //来自百度的关系词 有WD和WORD,分开处理
255                     string kwd = GetQuerystring(temp[0], url);                      //当以WD取不到的时候,则用WORD取词
256                     if (string.IsNullOrEmpty(kwd))                                  //指定对应的编码来消除乱码 
257                     {
258                         keyword = GetQuerystring(temp[1], url);                     //从URL中取得关键词的方法
259                        
260                     }
261                     else
262                     {
263                        keyword = kwd;
264                     }
265                 }
266                
271 else 272 { 273 keyword = GetQuerystring(_uOkw[i], url); 274 } 275 break; 276 } 277 } 278 279 string ecode = GBorUTF(keyword); //获得文字的编码格式 280 281 keyword = HttpUtility.UrlDecode(keyword, Encoding.GetEncoding(ecode)); 282 return keyword; 283 } 284 285 /// <summary> 286 /// 从URL地址中通过queryname提取关键词 287 /// </summary> 288 /// <param name="queryname">wd,word,q,query,w...</param> 289 /// <param name="url">URL地址</param> 290 /// <returns></returns> 291 private string GetQuerystring(string queryname, string url) 292 { 293 string keyword = string.Empty; 294 Dictionary<string, string> dic = new Dictionary<string, string>(); 295 string re = "[?&]([^=]+)(?:=([^&]*))?"; //通进正则将URL中参数分拆 放入字典中 296 MatchCollection mc = Regex.Matches(url, re); 297 foreach (Match item in mc) 298 { 299 if (item.Success) 300 { 301 dic.Add(item.Groups[1].Value, item.Groups[2].Value); 302 } 303 } 304 if (dic.ContainsKey(queryname)) //如果字典中有传入的匹配关键词的键,则取其值返回 305 { 306 keyword = dic[queryname]; 307 } 308 return keyword; 309 310 } 311 312 /// <summary> 313 /// 分析是哪种搜索引擎 314 /// </summary> 315 /// <param name="input"></param> 316 /// <returns></returns> 317 private string FromSearchengine(string input) 318 { 319 string SEngine = ""; 320 string[] Searchengine = { "google", "yahoo", "baidu", "soso", "bing", "sogou" }; 321 for (int i = 0; i < Searchengine.Length; i++) 322 { 323 if (input.Contains(Searchengine[i])) 324 { 325 SEngine = Searchengine[i]; 326 break; 327 } 328 } 329 330 return SEngine; 331 } 332 333 /// <summary> 334 /// 获取文字的编码 335 /// </summary> 336 /// <param name="input"></param> 337 /// <returns></returns> 338 private string GBorUTF(string input) 339 { 340 string en_code = "UTF-8"; 341 //abc -> UTF-8 -> abc2 342 string R_TO_U = HttpUtility.UrlDecode(input, Encoding.GetEncoding("UTF-8")); 343 string U_TO_R = HttpUtility.UrlEncode(R_TO_U, Encoding.GetEncoding("UTF-8")); 344 if (input.ToLower() != U_TO_R.ToLower()) 345 { 346 en_code = "GB2312"; 347 } 348 349 return en_code; 350 351 } 352 362 }


其实IP地址库是使用了CoralWry.dat;IP转用使用了一个类IPScaner.cs;IPSearchHelp.cs,这三个文件在网上有找到。

这次遇到最大的问题就是关键词乱码问题 ,首先为了避免乱码,就在JS代码编了一次,然后想到后台来解码,但是遇到了一个特别的问题 ,就是 从百度首页上直接搜索时,使用的是gb2312的编码格式,从其它站点嵌入百度搜索代码,搜索过来的时候,是utf-8的编码,soso,google是utf8,sogou是gb2312,还有使用不同的浏览器也会采用不同的编码,所以经常不是解决了这个就是哪个出现了问题,最后在网上搜到了一个比较通用的方法,就是假设一段内容是通过UTF8编码的,然后对它进行UTF8解码,再UTF8编码,如果得到的结果和最开始的结果相同,那么就是UTF8的编码,否则就是其它,由于现在基本上是GB2312和UTF8,所以就简单的处理了,当然这样处理不对,编码还有很多其它格式,我这里就是假定了,不是UTF8,就是GB2312,因为照现在所采集到的信息来看,这些搜索引擎 基本是使用了这两种方式。

目前都是写在这一个处理文件中的,由于只需要插入数据库,就直接在这个页面上进行插入了。

现在里面还有很多保留字段,目前这里有一个待解决的字段要采集,就是当用户打开了含有采集信息的JS代码的网站页面时,就会进行采集,并且F5刷新也会采集 一次,所以数据中还有一个字段就是判断是F5刷新 得到的数据还是正常采集得到的数据。

在网上查了一下,JS判断页面是否是刷新导致页面卸载,还是正常退出导致页面卸载的方法,好像都有一点点问题 。哪个大侠有好的处理方法,请指点一下小弟。

先更新到这。。。

不足之处,多多包涵!

 

posted @ 2012-07-22 15:31  孜默伊索男  阅读(1304)  评论(1编辑  收藏  举报