访问可视化(续)
之前写过一片文章:访问可视化,但是局限性很大,于是利用周末的时间,改造了一番。
打点的改造
老版本:在php里面进行打点
新版本:使用js加载空伪1px gif图片
数据分析和存储的改造
老版本:请求过来的时候,php分析,存进mysql
新版本:请求的时候,js分析,加载1px gif,nginx记录日志,python分析,存进数据库
数据的访问实时dump
老版本:监听mysql的binlog,publish到redis
新版本:分析nginx,存进数据库的同时,publish到redis
IP归属地 和 经纬度的查询
老版本:纯真数据库 + 百度地图地址反解
新版本:ip17mon + 腾讯地图行政区划latlag
预览
1. js的打点日志
具体可以参考:网站统计中的数据收集原理及实现
不过我使用的方法由文章简化而来。
2. nginx的日志记录
server {
listen 80;
listen 443 ssl;
server_name analytics.tool.lu;
ssl_certificate vhosts/tool.lu.chained.crt;
ssl_certificate_key vhosts/tool.lu.key;
root /data/html/analytics.tool.lu/public;
access_log off;
error_log off;
location / {
index index.html;
try_files $uri $uri/ =404;
}
location /__utm.gif {
expires -1;
if_modified_since off;
# add_header Last-Modified "";
empty_gif;
access_log /data/log/nginx/analytics.tool.lu.access.log;
}
}
3. nginx日志的分析
这里有几点要注意的:
- nginx日志我是使用logrotate切分的,要达到实时读取nginx日志的目的,需要保证读取的文件是最新切分出来的文件,而且在切分文件的时候要保证之前的文件已经处理完毕。
- 记录日志文件处理的offset,又是由于logrotate切分nginx日志的原因,如何保证记录的offset是唯一的,且能对应上日志文件,这里我使用了log文件创建的时间作为标识(在linux下是不储存文件的创建时间的,需要自己记录实现)。
- nginx log中时间格式的解析,基本上就是抓瞎了(不是所有版本的python strptime都支持timezone的)
- 如何通过腾讯地图 api 返回的数据建立索引,方便快速查找到 地址对应的经纬度
为了安全性考虑,这边就不贴 nginx log 解析的完整代码了。
ua-parser返回version的拼接
def version(self, vs):
v = ''
if not vs['major']:
return v
v += vs['major']
if not vs['minor']:
return v
v += '.' + vs['minor']
if not vs['patch']:
return v
v += '.' + vs['patch']
if not 'patch_minor' in vs or not vs['patch_minor']:
return v
v += '.' + vs['patch_minor']
return v
腾讯地图行政区划数据索引的建立
# IP17MON返回的数据带有,省市,可以优先市级别的索引,再省级别的索引
def index(self):
for province in self.data['result'][0]:
self.indexed_provinces[province['name']] = province['location']
for city in self.data['result'][1]:
self.indexed_cities[city['name'] if 'name' in city else city['fullname']] = city['location']
python
list 的 shift
l = [1, 2]
first = l.pop(0)
parse nginx log的正则
self.pattern = re.compile(r'(?P<ipaddress>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) - - \[(?P<dateandtime>\d{2}\/[a-z]{3}\/\d{4}:\d{2}:\d{2}:\d{2}) [+-]\d{4}\] ((\"(GET|POST) )(?P<url>.+)(http\/1\.1")) (?P<statuscode>\d{3}) (?P<bytessent>\d+) (["](?P<referrer>(\-)|(.+))["]) (["](?P<useragent>.+)["])', re.I)
nginx log时间的解析
datetime.datetime.strptime(fields['dateandtime'], '%d/%b/%Y:%X')
PS: 好久不写python已有些生疏
一直都没明白PYTHON是个神马东西。啥时候都用这个编程了。。
你什么时候回的地球?