用python打造自己的网站日志分析工具(一)-拷贝

东尧爱分享

这是东尧每天一篇文章的第28天

东尧写文章的目标:分享东尧的经验和思考,帮你获取物质和精神两方面幸福。

日志分析在SEO中有着非常重要的作用,通过日志分析我们可以看到蜘蛛的各种抓取状态,分析热门页面,提取错误页面等等。

今天要教大家的就是使用python来打造一个简单的日志分析工具,对我们的网站日志进行归类分析。

1

工具效果

对日志内容进行分类并统计分析。

2

需求分析

统计每个搜索引擎蜘蛛的来访次数

统计每个搜索引擎都访问了哪些页面

统计访问最多的页面和目录

统计抓取成功和失败的页面及次数

统计蜘蛛IP及其访问次数

3

程序设计

存储设计

将结果保存到CSV文件中,每个搜索引擎分成独立的文件(以下案例使用Baiduspider进行示范)

程序计算临时存储设计

(使用字典来存放,因为字典有键值对方便对应和查找)

统计每个搜索引擎蜘蛛的来访次数(visits)

统计每个搜索蜘蛛IP及其来访次数(visit_spiders)

统计每个搜索引擎都访问了哪些页面及次数(visit_pages)

统计访问了哪些目录及次数(visit_path)

统计抓取失败的页面和次数(visit_error)

baidu = {} # 创建针对百度蜘蛛的字典

baidu['visits'] = 0 # 统计总访问次数

baidu['visit_spiders'] = {} # 统计蜘蛛IP及次数,键是字符串,值是字典,可放置蜘蛛IP和来访次数

baidu['visit_pages'] = {} # 统计访问页面

baidu['visit_dirs'] = {} # 统计访问目录及次数

baidu['visit_error'] = {} # 统计状态码及次数

日志读取分析

如果要实现以上数据维度的分析,那么日志文件里面必须包含访问者的ip、状态码、访问了哪些页面、以及访问者的UA(user-agent用户代理),否则就无法分析出来。

识别搜索引擎和正常用户主要就是通过UA来判断的。

网站日志基本都是每行一条记录的,每个字段信息之间是用空格分开的,因此只需要遍历日志文件的每一行,然后用空格来拆分每个字段,提取需要的字段信息即可。下面是一条日志的样子:

220.181.125.138 - - [17/Feb/2017:00:00:13 +0800] "[www.brooks.com] GET /xiaoxuejiaoyu/ernianji/ernianjixiaceshuxueko/48265.html HTTP/1.1" 200 6667 "-" "Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)" "-""request_time 0.122""upstream_response_time 0.122"

此条日志信息详细的记录了访问者的ip、访问时间、时区、访问的域名、请求 方式、访问页面、http版本、请求状态码、服务器返回字节数、用户代理、请求时间、响应时间等字段信息。

代码实现

使用for循环来遍历文件

使用成员操作符(in)来判断搜索引擎蜘蛛是否存在日志记录中,如果存在则将对应蜘蛛的访问次数加1

with open('2017-02-17.log') as logfile: # 用with方法打开文件可以不用手动关闭文件

print('开始分析日志')

for line in logfile:

if 'Baiduspider' in line:

baidu['visits'] += 1 # 百度蜘蛛访问次数+1

然后使用字符串的split方法来切割字符串,将字符串转成列表。通过列表的下标获取需要的字段

item = line.split() # split方法默认用空格来做切分

提取蜘蛛IP,然后作为字段的键名,通过字典的get方法来判断字典中是否已经存在相同的ip,如果不存在则新建一个键名,然后值设置为1,如果存在则将对应的值加1

# 获取蜘蛛IP及其访问次数

spider = item[0] # 将蜘蛛IP提取出来

if baidu['visit_spiders'].get(spider):

baidu['visit_spiders'][spider] += 1 # 如果此IP在字典内,则对此蜘蛛访问次数值加1

else:

baidu['visit_spiders'][spider] = 1 # 如果IP不存在,则将此新IP创建到字典里

提取URL:跟蜘蛛ip一样的操作

提取404状态码(错误页面)信息,通过判断 item[9]是否为‘404’就可以进行操作。

提取访问目录:目录的提取是将URL使用字符串的split方法以斜杠进行拆分,先判断URL是否包含两个及以上的斜杠,如果是就拆分,如果是首页就不拆分。然后只提取第一个目录再使用join方法重新拼接成字符串,然后跟URL一样的操作。

# 获取蜘蛛访问目录及其次数

if url == '/': # 判断url是否为根目录

dirname = '/'

elif url.count('/') >=2: # 判断url是否有二级目录

# 只获取一级目录

dirname = '/%s/' % url.split('/')[1]

else:

dirname = '' # 空字符串为False

if dirname and baidu['visit_dirs'].get(dirname): # 同时满足目录存在和字典中有此目录

baidu['visit_dirs'][dirname] += 1

elif dirname:

baidu['visit_dirs'][dirname] = 1

对上面的蜘蛛ip、访问页面、访问目录、错误页面的结果进行从大到小的倒序排序(都是字典):

# 对统计结果的字典进行排序

# sorted方法返回的是排序后的列表

# 每个列表的元素是由双元素元组组成的(主要是因为iteritems方法得到的就是双元素元组)

# 元组的第一个元素是字典的key(键),第二个元素是字典的value(值)

sort_spider = sorted(baidu['visit_spiders'].items(),key = lambda x: x[1],reverse=True)

sort_pages = sorted(baidu['visit_pages'].items(), key = lambda x: x[1], reverse=True)

sort_dirs = sorted(baidu['visit_dirs'].items(), key = lambda x: x[1], reverse=True)

sort_error = sorted(baidu['visit_error'].items(), key = lambda x: x[1], reverse=True)

判断哪个字段得到的数量是最多的(因为写入文件的时候要以最多的为准,只有知道哪个是最多的,才知道要写入多少行数据,用于for循环写入),但是蜘蛛ip的数量肯定不会有页面数量多,目录的数量也不会有页面的数量多,错误页面的数量也不会有页面的数量多(页面包括了错误页面),所有只需要得到页面的数量就好了。

要将结果写入csv文件,需要在开头引入csv模块。csv模块的使用方法在下面注释, 要解决Excel打开utf-8编码的csv文件中文乱码问题,需要在open文件时写入encoding='utf-8'就好了:

# -*- coding: utf-8 -*-

import csv

save_file = open('baiduspider.csv','w',encoding='utf-8') # w模式会将\n写入进去,结果文件中会自动多一行

fields = ('总访问量','蜘蛛IP','IP访问次数','受访目录','目录受访次数','受访页面','页面访问次数','404页面','出错次数')

csvwriter = csv.writer(save_file) # 将save_file写入到csvwriter中

csvwriter.writerow(fields) # 将fields的每个元素作为每一列

因为遍历的页面数量的列表,因此别的列表的信息可以使用pop方法来获取,当列表为空的时候就证明获取完了,然后就将值设置为空字符串,这样的话只有列表有数据的时候才会把数据写入到文件,没有数据的时候写入的就是空字符串(其实就是啥都没有)。

同时由于蜘蛛的访问总数只在第一行,也就是下标为0的时候,其余时候写入空字符串,上面两种情况都需要做判断。又因为页面的数量是最多的,所以直接遍历页面的排序结果列表就OK了。

# 将结果写入文件

row_list = ['' for _ in range(9)] # 单独的下划线表示一个占位变量,不需要用到它

for page_item in sort_pages:

row_list[0] = baidu['visits'] if sort_pages.index(page_item) == 0 else '' # 如果下标为0则返回baidu['visits'],否则返回空

除了百度蜘蛛以外,还有360蜘蛛、搜狗蜘蛛、谷歌蜘蛛等等,那这么多蜘蛛我们不可能把上述程序又重新全部敲一遍,这样代码会非常冗长。

因为针对每个搜索引擎蜘蛛,除了存储结果的名称不一样,整个处理的流程都是一样的,因此我们可以将这些流程封装成两个函数一个专门处理日志,一个用于统计结果和保存文件,这样针对不同的蜘蛛,只需要传入需要处理的日志的行信息、存放的字典名以及保存结果的文件名即可。

具体的封装函数下一节的教程中我会再为大家详细介绍,欢迎继续关注。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180505G0U8PE00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券