一个乐于分享的博客
关注互联网折腾服务器分享码农的日常

百度统计原理分析-利用PHP/Python实现模拟访问

百度统计原理分析-利用PHP/Python实现模拟访问

国内大多数站长可能都在用百度统计。统计的使用方法也很简单,只要在需要统计的页面底部加上统计代码即可。然后打开百度统计的后台,就能看到访客信息,包括入口页面,停留时间,跳出率等等,很是方便。

使用当然是会用,但是随着不断成长,逐渐开始考虑一些事情,比如百度统计只是一行JS怎么就实现统计了呢?如果不打开网页,是不是能利用脚本模拟这一过程呢?

与是就开始上网查资料,开始了新一轮的折腾。网上的研究百度统计的不多,我找到了李鑫博客的原理分析模拟访问

原理分析

统计代码

首先,百度统计要求网站必须嵌入一段JS代码,大概是长这个样子的。

var _hmt = _hmt || [];
(function() {
 var hm = document.createElement("script");
 hm.src = "https://hm.baidu.com/hm.js?65e1c6689693082cffb3b7e1f2d8027f";
 var s = document.getElementsByTagName("script")[0]; 
 s.parentNode.insertBefore(hm, s);
})();

去除掉多余的代码,得到最重要的一行

https://hm.baidu.com/hm.js?65e1c6689693082cffb3b7e1f2d8027f

即引入这个JS文件就能实现统计了,问题后边的32位字符串就是每个站点特有的统计ID

hm.js做了些什么

该代码加载时,会往用户浏览器中写入名为“HMACCOUNT”的永久cookie,有效期至2038年,以此来区分用户身份。

同时会获取客户端环境,包括浏览器版本,屏幕分辨率,色深,语言等信息。

总结如下:

cc: 不知道,一般为1
cf:url参数hmsr的值
ci:url参数hmci的值
ck:是否支持cookie 1:0
cl:颜色深度 如 “32-bit”
cm:url参数hmmd的值
cp:url参数hmpl的值
cw:url参数hmkw的值
ds:屏幕尺寸,如 ‘1024×768’
ep:初始值为’0’,时间变量,反映页面停留时间,格式大概是:现在时间-载入时间+“,”+另一个很小的时间值
et:初始值为’0’,如果ep时间变量不是0的话,它会变成其他
fl:flash版本
ja:java支持 1:0
ln:语言 zh-cn
lo: 不知道,一般为0
lt:日期 time.time(),如“1327847756”, 在首次请求没有
nv: 不知道,一般为1或者0
rnd:十位随机数字
sb:如果是360se浏览器该值等于‘17’
se: 和搜索引擎相关
si:统计代码id
st:
su:上一页document.referrer
sw: 不知道,估计和搜索引擎有关,一般为空
sse:不知道,估计和搜索引擎有关,一般为空
v:统计代码的版本 ,目前该值为“1.2.30”

发送请求

当获取到所有信息的时候,就可以向服务器提交请求了,将之前获取到的参数进行整合,并以这些参数为后缀请求hm.gif,大概是这样一个地址

https://hm.baidu.com/hm.gif?cc=0&ck=1&cl=24-bit&ds=1440x900&vl=372&ep=7626%2C3009&et=3&fl=29.0&ja=0&ln=zh-cn&lo=0&lt=1524041576&rnd=1839110354&si=65e1c6689693082cffb3b7e1f2d8027f&su=https%3A%2F%2Fyantuz.cn%2F275.html&v=1.2.30&lv=3&sn=28783&u=https%3A%2F%2Fyantuz.cn%2F

模拟访问

既然了解了请求原理,那能不能用脚本实现模拟访问呢?答案当然是可以的

百度统计的4个请求

通过控制台我们可以发现,每访问一个页面都会产生4个请求

百度统计原理分析-利用PHP/Python实现模拟访问

  1. 加载hm.js
  2. 加载完毕时候出发两次请求,并传递参数
  3. 退出页面时候,发出一次请求,并传递参数

实际模拟时,只需要前三次请求即可在访问记录中看到访客记录。

python模拟访问

import urllib2
import urllib 
import random
import math
import urlparse
import time
import cookielib

########################################################################
class Baidu:
 """"""
 Referer='http://www.lixin.me'
 TargetPage='/www.lixin.me'
 BaiduID=''
 Hjs="http://hm.baidu.com/h.js?"
 Hgif="http://hm.baidu.com/hm.gif?"
 UserAgent='Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' #IE9
 MyData={'cc':'1','ck':'1','cl':'32-bit','ds':'1024x768','et':'0','ep':'0','fl':'11.0','ja':'1','ln':'zh-cn','lo':'0','nv':'1','st':'3','v':'1.0.17'}
 #----------------------------------------------------------------------
 def __init__(self,baiduID,targetPage=None,refererPage=None):
 """Constructor"""
 self.TargetPage=targetPage or self.TargetPage
 self.Referer=refererPage or self.Referer
 self.BaiduID=baiduID
 self.MyData['si']=self.BaiduID
 self.MyData['su']=urllib.quote(self.Referer)
 pass
 def run(self,timeout=5):
 cj=cookielib.CookieJar()
 opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) 
 opener.addheaders=[("Referer",self.TargetPage),("User-Agent",self.UserAgent)]
 try:
 response=opener.open(self.Hjs+self.BaiduID).info()
 self.MyData['rnd']=int(random.random()*2147483647 )
 self.MyData['lt']=int(time.time())
 fullurl=self.Hgif+urllib.urlencode(self.MyData)
 response2=opener.open(fullurl,timeout=timeout).info()
 self.MyData['rnd']=int(random.random()*2147483647 )
 self.MyData['et']='3'
 self.MyData['ep']='2000,100'
 response3=opener.open(self.Hgif+urllib.urlencode(self.MyData),timeout=timeout).info()
 pass
 except urllib2.HTTPError ,ex:
 print ex.code 
 pass
 except urllib2.URLError,ex:
 print ex.reason
 pass
 pass
 
 
 
if __name__ =="__main__":
 a=Baidu('百度统计id','https://yantuz.cn','yantuz.cn')
 a.run()

php模拟访问

function baiduVisit($bdId,$targetUrl,$referer = 'yantuz.cn',$visitTimes=1){
 $bdjs = 'https://hm.baidu.com/hm.js?';
 $bdgif = 'https://hm.baidu.com/hm.gif?';
 //$bdId = '65e1c6689693082cffb3b7e1f2d8027f';

$arr=array(
 'cc'=> '0',
 'ck'=> '1',
 'cl'=>'24-bit',
 'ds'=> '1440x900',
 'vl'=> '747',
 #'ep'=> '6346,2301',#时间
 'et'=> '0', #3
 'fl'=> '29.0',
 'ja'=> '0',
 'ln'=> 'zh-cn',
 'lo'=> '0',
 'lt'=> time(),
 'rnd'=> rand(1000000000,2000000000), #random
 'si'=> $bdId,
 'v'=> '1.2.30',
 'lv'=> '3',
 'sn'=> '25573',#25581
 'su'=> $referer, #请求来源

#'ct'=> '!!',
 #'tt'=> '页面标题'
 );
 //echo http_build_query($arr);

// Create a stream
 $opts = array(
 'http'=>array(
 'method'=>"GET",
 'header'=>"Accept-language: cn\r\n"."referer:$targetUrl",
 'timeout'=>3,
 )
 );
 $context = stream_context_create($opts);
 $url1 = $bdjs.$bdId;
 //echo $url1.'<br />';
 $arr1 = array_merge($arr,array('ep'=> '2302,153','u'=> $referer));
 $arr1['et'] = 3;
 $url2 = $bdgif.http_build_query($arr1);
 //echo $url2.'<br />';
 $arr2 = array_merge($arr,array('ct'=> '!!','tt'=> 'title'));
 $url3 = $bdgif.http_build_query($arr2);
 //echo $url3.'<br />';

for ($x=0; $x<$visitTimes; $x++) {
 file_get_contents($url1, false, $context);
 file_get_contents($url2, false, $context);
 file_get_contents($url3, false, $context);
 //echo $x;
 }
}

baiduVisit('百度ID','https://yantuz.cn/');

博主实测

首先准备好代码,以PHP为例,如果要得到一个来自xxoo.com的访问记录,那么调用方法为

baiduVisit('65e1c6689693082cffb3b7e1f2d8027f','https://yantuz.cn','https://xxoo.com');

百度统计原理分析-利用PHP/Python实现模拟访问

此法纯属YY装逼,再次感谢大佬李鑫的博客研究成果。其余用法可自行开发,有好想法的欢迎留言交流。

转载务必注明出处:岩兔站 » 百度统计原理分析-利用PHP/Python实现模拟访问
赞 (2) or 打赏

讨论区 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址