如何把百度统计代码放入JS文件中?百度统计的JS脚本原理分析
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?68df874fd78fd8f5cdv45fd470a49b12";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
首先,百度统计会要求我们在要统计的页面中嵌入一段js语句,类似如下:
<script type=”text/javascript”>
var _bdhmProtocol = ((“https:” == document.location.protocol) ? ” https://” : ” http://”);
document.write(unescape(“%3Cscript src=’” + _bdhmProtocol + “hm.baidu.com/h.js%3F3266e9d3684eaa1337dc7c4b4b64b0ae’ type=’text/javascript’%3E%3C/script%3E”));
</script>
这段js,实质上是往页面中引入hm.baidu.com/h.js的这段代码,该代码的内容会根据后面的参数有所不同,h.js?后面的参数就是你在百度统计里的id。
获取该h.js代码的同时,百度统计会往你的浏览器写入一个名字为“HMACCOUNT”的cookie,该cookie的过期时间为2038年,所以只要你没有清空浏览器cookie,基本就永不过期。
h.js被下载后,便执行其脚本获取一些浏览器相关信息和访问来源,获取的信息包括屏幕尺寸、颜色深度、flash版本、用户语言等。
从js代码中可以得到,所有参数包括这些:”cc,cf,ci,ck,cl,cm,cp,cw,ds,ep,et,fl,ja,ln,lo,lt,nv,rnd,sb,se,si,st,su,sw,sse,v”。这些参数的意义大致如下:
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.0.17”
当这些参数都设置完毕了(有些参数并没有赋值),筛选出已经赋值了的参数,并作为hm.baidu.com/hm.gif的参数拼凑出一个url,如:http://hm.baidu.com/hm.gif?cc=1&ck=1&cl=32-bit&ds=1366×768&ep=0&et=0&fl=11.0&ja=1&ln=zh-cn 。然后请求该图片。
百度统计服务端,通过接收到这个请求,并从这个图片的网址附带的参数获取相关信息,记录访客访问记录;当页面被用户关闭的时候,同样会触发一次请求hm.gif的过程,但这个过程不是所有浏览器和所有关闭动作都支持。
接下来通过程序模拟这一过程:
首先,使用Wireshark(一款网络抓包工具)对浏览器实际的过程进行捕获。首先是使用ie打开一个有超链接链接到有百度统计的网站,加载完毕后关闭浏览器。最后在Wireshark上得到这么的网络数据包。
http://hm.baidu.com/h.js?3266e9d3684e7a1307dc7c4b4a64b0ae
http://hm.baidu.com/hm.gif?cc=1&ck=1&cl=32-bit&ds=1366×768&ep=0&et=0&fl=11.0&ja=1&ln=zh-cn&lo=0<=1328171561&nv=1&rnd=2889921&si=3266e9d3684e7a1307dc7c4b4a64b0ae&st=3&su=http%3A%2F%2Fwww.zhanghangbo.com%2F&v=1.0.17
http://hm.baidu.com/hm.gif?cc=1&ck=1&cl=32-bit&ds=1366×768&ep=7289%2C115&et=3&fl=11.0&ja=1&ln=zh-cn&lo=0<=1328171561&nv=1&rnd=1444115283&si=3266e9d3684e7a1307dc7c4b4a64b0ae&st=3&su=http%3A%2F%2Fwww.zhanghangbo.com%2F&v=1.0.17
http://hm.baidu.com/hm.gif?cc=1&ck=1&cl=32-bit&ds=1366×768&ep=212486%2C4614&et=3&fl=11.0&ja=1&ln=zh-cn&lo=0<=1328171541&nv=1&rnd=1067394506&si=0f9e2caa14d6d0a51371b168d182314a&st=1&v=1.0.17
可以发现,浏览器总共向服务器端发送了4次请求:
- 请求一段js脚本。
- 加载完毕时候出发一次请求,并传递参数
- 退出页面时候,发出一次请求,并传递参数,与上面对比,发现ep参数有变化。
百度统计是基于cookie的,当请求js脚本的时候,会在你电脑里保存一个永久cookie,该cookie作为你的用户标识。同时发现,但退出时候参数ep从最开始的0变为了“7289%2C115”,转义后是“7289,115”这是两个毫秒单位,即7.2秒和0.1秒的意思。同时前两次请求hm.gif的时候lt参数(时间,javascript:(new Date).getTime())是不变的。rnd随机数每次都变。
下面我们就来模拟一次请求,本次使用的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','http://www.lixin.me/blog/test4','www.lixin.com.cn')
a.run()
如何把百度统计代码放入JS文件中?百度统计的JS脚本原理分析的更多相关文章
- JavaScript进阶(二)在一个JS文件中引用另一个JS文件
在一个JS文件中引用另一个JS文件 转载地址:http://blog.csdn.net/zndxlxm/article/details/7875787 方法一 在调用文件的顶部加入下例代码 ...
- 在一个JS文件中引用另一个JS文件
方法一,在调用文件的顶部加入下例代码: document.write(”<script language=javascript src=’/js/import.js’></scrip ...
- JS文件中加载jquery.js
原文链接:http://blog.csdn.net/whatday/article/details/39553451 最近有一个需求: 1.在一个html中只能引入一个JS文件 不能有JS代码和其他J ...
- 由js文件中引入另外的js文件想到的
1. html中,使用<script src="../static/js/xxx.js"></script>引入js文件. 2. 在js文件中,引入js ...
- JS文件中引用另一个JS文件
1.生产项目上遇到一个Bug,需要修改JS文件,添加Jquery代码,但是原来的页面没有添加对Jquery文件的引用,无法修改原来的页面(自动生成的HTML) 这就需要在JS文件中添加对Jquery文 ...
- Js- 在一个JS文件中引用另一个JS文件
在调用文件的顶部加入下例代码: document.write(”<script language=javascript src=’/js/import.js’></script> ...
- js文件中模块化导入swiper.js文件方法
es6导入: 在js文件顶端 import Swiper from "../../assets/javascripts/swiper.min"; import '../../ass ...
- js文件中调用另一个js文件:
document.write("<script language='javascript' src='/UEditor/uparse.js'></script") ...
- 如何在一个js文件中引入另外的js文件
例如想要在a.js中引用b.js.c.js和d.js document.write("<script language='javascript' src='b.js'></ ...
随机推荐
- 关于 Touchjs 手势识别事件库 this 关键字与选择器不对称情况
Touchjs 版本 v0.2.14 废话不多,直接看代码,一个拖动实例 <div id="touch-drag"></div> <script ty ...
- 使用python读取word,写入execl
word里面有2张表,需要找到第二张表,并写入execl中: 代码如下: #coding:utf-8 import os from docx import Document import win32c ...
- Linux源码-等待队列注释
等待队列 Linux中了等待队列的毒,代码中充斥着等待队列.不信你翻翻代码. 等待队列的唤醒我们这里叫激活.免得和线程唤醒混淆. 数据结构 头结点wait_queue_head_t的结构 struct ...
- AngularJs踩过的坑
1. 使用checkbox和radio时, 不能使用ng-model直接绑定原始对象, 需要绑定一个对象的某个子属性, 才能把值绑定到scope <label><input type ...
- Linux(CentOS 7)环境下安装MySQL
在CentOS中默认安装有MariaDB,但是我们需要的是MySQL,安装MySQL可以覆盖MariaDB MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 ...
- 目标检测网络之 YOLOv2
YOLOv1基本思想 YOLO将输入图像分成SxS个格子,若某个物体 Ground truth 的中心位置的坐标落入到某个格子,那么这个格子就负责检测出这个物体. 每个格子预测B个bounding b ...
- Python十题(第2课)
一.天天向上的力量 C 一年365天,以第1天的能力值为基数,记为1.0.当好好学习时,能力值相比前一天提高N‰:当没有学习时,由于遗忘等原因能力值相比前一天下降N‰.每天努力或放任,一年下来的能力值 ...
- php 类接口继承练习
<?php /** * @hypo 接口的特性:接口中定义的所有方法都必须是public 接口的实现:一个接口可以使用implements操作符,类中必须实现接口中的所有方法,否则会报fatal ...
- codeforce round#466(div.2)C. Phone Numbers
C. Phone Numbers time limit per test2 seconds memory limit per test256 megabytes inputstandard input ...
- 云服务器Windows Server2012 配置http服务器(又称Web服务器,IIS)
出错:无法打开运行空间池.服务器管理器WinRM插件可能已损坏或丢失. 解决方法: http://shiyousan.com/post/636308065767125916 第一步是开启WinRM服务 ...