使用pandas进行SEO日志分析
来源:互联网 发布:java递归算法详解 编辑:程序博客网 时间:2024/06/05 01:03
http://www.jianshu.com/p/84d4f9c6e83f
虽然网络上有比较多的SEO日志分析工具,比如爱站,光年,但那都是固定维度的,不如自己写的灵活,想怎么拆分就怎么拆分,加上最近在学习《利用python进行数据分析》这本书,正好可以用来练习练习,顺便熟悉一下pandas库。不得不说,pandas这个库真的强大的不要不要的,对数据的加载、存储、清理、转换、合并样样兼顾,虽然目前只看到第9章,但是感觉对数据的处理能力有了很大的进步!
对于SEO日志分析,比较常用拆分维度是:
- 统计总抓取量
- 统计不重复抓取量
- 统计状态码数量
- 统计目录的抓取量
- Top N抓取量
此外,我参考了光年日志分析工具,也加入了停留时间和访问时间,尽量把维度拆分的细一点多一点(练手嘛),但是,如果按我想的那样,拆分的很细的话,那肯定要写很多行代码(事实上,没用pandas写之前,就用了400多行代码实现过一个demo),所以取巧了一下,拆分成需要的数据之后,用pivot_table
的方法建立透视表。
日志的格式如下:220.181.108.81 - - [05/Mar/2016:20:41:23 +0800] "GET /images/im_qq.gif.pagespeed.ce.8GQAmIPgsj.gif HTTP/1.1" 200 4581 "http://\w+.\w+.com/\d+.html" "Mozilla/5.0 (Windows NT 6.2; Trident/7.0; MANM; ED; rv:11.0) like Gecko"
日志分析脚本demo如下:
# -*- coding: utf-8 -*-'''爬虫日志分析demo1.0'''from time import strptime,mktime,timefrom pandas import Series,DataFrameimport pandas as pdimport sys,socketreload(sys) sys.setdefaultencoding('utf-8')start = time()format = "%d/%b/%Y:%H:%M:%S" #写出日志的日期格式def file_open(file): col_names=['ip','datetime','resource','status','bytes','refer','ua','path','level1','data'] reader = pd.read_csv(file,sep='\s+',header=None,chunksize=1000000,names=range(10)) data = DataFrame(columns=col_names) for piece in reader: data[['ip','status','bytes','refer','ua']] = piece[[0,6,7,8,9]] data['refer'] = data['refer'].fillna('abc') data['datetime'] = piece[3].str.replace('[','') data['resource'] = piece[5].str.split(' ').str[1] data['data'] = piece[3].str.match('\[(\S+):\d+:\d+:\d+').str[0] data['path'] = piece[5].str.match('\w+\ ((?:/[A-Za-z0-9-_/\.]*/)|(?:/)\W)').str[0].str.strip() data['level1'] = piece[5].str.match('\w+\ ((?:/[\w\d_-]*/)|(?:/) )').str[0].str.strip() return data'''判断爬虫真假'''def check_spider(df): start = time() ip = list(df['ip'].unique()) print u'正在检查spider真伪,共%s个待查询iP,耗时较长,请稍等' % len(ip) true_spider = [] fake_spider = [] for x,y in enumerate(ip): try: result = socket.gethostbyaddr(y)[2][0] true_spider.append(result) print 'NO.%s %s is spider and now appending in true spider list' % (x,y) except socket.herror, e: print 'NO.%s %s is facke spider' % (x,y) fake_spider.append(y) log = df[df['ip'].isin(true_spider)] print u'执行完成,共耗时%s秒' % (time()-start) print 'True Spider IP %s,False Spider IP %s' % (len(true_spider),len(fake_spider)) return log'''提取某个爬虫访问记录'''def get_spider_log(df,spider): spiders = df['ua'].str.contains(spider) spider_log = df[spiders] spider_log['datetime'] = spider_log['datetime'].apply(lambda x:int(mktime(strptime(x,format)))) return spider_log'''统计停留时间和访问次数'''def get_x(x): a = [] a.append(x) return adef get_list(list_name): '''后一个减去前一个,计算时间差''' t_list = list(list_name) #传入的是一个Serice对象,所以要转化成list t_list.sort() values = [] weight = len(t_list) for value in xrange(weight): if weight == 1: #只有一个时间的情况,停留时间算成1秒 values.append(1) elif value > 0: #前面是升序,所以要 >0 才能用后一个减去前一个 values.append((t_list[value]-t_list[value-1])) ''' size 是大于1799的个数,因为间隔1800秒以上访问次数+1,大于1799是包含了1800''' size = len(filter(lambda x:x >1799,values)) '''如果有一个大于1800秒,表示共访问了2次,有 N 个,表示访问了 N+1 次''' visits = size + 1 '''过滤大于1800的值,因为过滤前可能是[1811,2],有两个停留时间,过滤后变成[2]只剩一个时间,因此加上size修正''' _values = filter(lambda x:x <1800,values) #访问时间差的列表 '''存在过滤后为空列表的情况,但只要访问过,就有停留时间''' if _values == []: _values.append(1) stay_time = reduce(lambda x,y:x+y,_values) + size result = [visits,stay_time] return resultif __name__ == '__main__': script,file,output = sys.argv log = file_open(file) spider_log = get_spider_log(log,'Baiduspider') #默认百度爬虫 spider_log = check_spider(spider_log) #检查爬虫真伪 drop_dup = spider_log.drop_duplicates(['data','resource']) #去除'resource'列中的重复项,算不重复抓取量用 '''不重复抓取量''' No_rep = drop_dup.pivot_table(values=['resource'],index=['data','level1','path'],aggfunc='count') No_rep.columns = ['No_rep'] '''次级目录总抓取数,数数的时候会按层次化索引来数,所以数'ua'列也可以''' All_crawl = spider_log.pivot_table(values=['ua'],index=['data','level1','path'],aggfunc='count') All_crawl.columns = ['All_crawl'] '''次级目录总字节数''' All_bytes = spider_log.pivot_table(values=['bytes'],index=['data','level1','path'],aggfunc='sum') All_bytes.columns=['All_bytes'] '''平均抓取字节(总抓取字节/抓取量)''' Avg_bytes = pd.Series(All_bytes['All_bytes']/All_crawl['All_crawl'],index=All_crawl.index,name='avg_bytes') '''次级状态码数量''' All_status = spider_log.pivot_table('resource',index=['data','level1','path'],columns=['status'],fill_value=0,aggfunc='count') '''算出停留时间和访问次数''' t = spider_log['datetime'].groupby([spider_log['data'],spider_log['ip'],spider_log['level1'],spider_log['path']]).apply(lambda x:get_x(x)) t = t.apply(lambda x:get_list(x[0])).reset_index() t['visits'] = t[0].str.get(0) t['saty_time'] = t[0].str.get(1) '''停留时间和访问次数''' visits_stay = t.pivot_table(index=['data','level1','path'],aggfunc='sum') ''' 平均停留时间(总停留时间/总抓取量)'' Avg_saty = pd.Series(visits_stay['saty_time']/All_crawl['All_crawl'],index=All_crawl.index,name='Avg_saty') '''次级目录IP访问数量''' Ip_count = t.pivot_table('ip',index=['data','level1','path'],aggfunc='count') '''精确到次级目录''' last = No_rep.join([Ip_count,All_crawl,All_bytes,Avg_bytes,Avg_saty,visits_stay,All_status]).reset_index() '''精确到一级目录''' no_path = last.pivot_table(index=['data','level1'],aggfunc='sum') no_path['avg_bytes'] = pd.Series(no_path['All_bytes']/no_path['All_crawl'],index=no_path.index) no_path['Avg_saty'] = pd.Series(no_path['saty_time']/no_path['All_crawl'],index=no_path.index)# last.to_csv('ulast.csv',index=False) no_path.to_csv(output) #默认输出 over = time() print '***Analysis OK!Take %s seconds***' % (over-start)
导出的结果如下:
这里说一下页面停留时间计算原理,因为日志的记录里只记录了进入页面的时间,并没有记录停留时间,所以只能间接地算出来。比如:A IP 访问了1和2两个页面,那么1页面的停留时间=2页面的进入时间-1页面的进入时间。由于A IP 没有访问第3个页面,所以算不到第2个页面的停留时间,我这里人为的当成停留了1秒。
总停留时间的计算思路是按 IP 和目录分组,得到每个目录的时间列表,然后列表里的后一个数减去前一个数得出时间差,过滤时间差>1799的数,然后累加,算出每个目录的总停留时间。而访问数量就是>1799的数量+1。
另外,脚本算出来的总停留时间和光年日志分析工具的会不一样,不过那并不碍事,本来总停留时间就是一个参考,同一个标准算出来的数据对最后的结论影响不大。
最后,如果是用 shell 进行SEO日志分析的话,可与阅读这篇文章:
使用shell分析日志——老狼
作者:担得一身好酱油
链接:http://www.jianshu.com/p/84d4f9c6e83f
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 使用pandas进行SEO日志分析
- 使用 Pandas 分析 Apache 日志
- 使用 Pandas 分析网站访问日志
- Python 使用 pandas 进行数据分析
- 使用hive进行日志分析
- 使用python,pandas对外汇储备进行预测分析
- PythonStock(12):使用python,pandas进行股票分析
- python+pandas分析nginx日志
- 使用Shell对apache日志进行分析
- 使用objdump进行Android crash 日志 分析
- 使用pandas进行数据清洗
- 使用pandas进行数据清洗
- 利用Python 的 Pandas进行数据分析
- 利用python进行数据分析-pandas入门
- 《利用Python 进行数据分析》pandas 总结
- 【量化小讲堂-Python&Pandas系列01】如何快速上手使用Python进行金融数据分析
- SEO优化每天网站日志分析
- iis日志分析 seo必备技能
- linux下的jpeg解码库使用
- 搞学术离不开的那些数学(概率论与数理统计)—第一章概率论基本概念
- 傣妈米线加盟优势:做好万全准备只为与您相遇
- [leetcode] 29. Divide Two Integers
- 在 Asp.NET MVC 中使用 SignalR 实现推送功能
- 使用pandas进行SEO日志分析
- Struts2入门(11):文件上传与单文件/多文件上传示例
- E
- 反射重点
- IIC专题(一)——基础知识准备
- csu1106 记忆化搜索+最短路
- pychram快速创建类和方法
- MYSQL备份与恢复精华篇
- PythonStock(5):使用 dataTable+python 实现服务端多字段排序