基本需求 90%
1 统计本日志文件的总pv、uv
2 列出全天每小时的pv、uv数
3 列出top 10 uv的IP地址,以及每个ip的pv点击数
4 列出top 10 访问量最多的页面及每个页面的访问量
5 列出访问来源的设备列表及每个设备的访问量
名词解释:
pv:page visit , 页面访问量,一次请求就是一次pv
uv: user visit, 独立用户,一个ip就算一个独立用户 分行是谈你你
注意:没有ip的可以认为是异常日志,不用统计!
1:split()函数
语法:str.split(str="",num=string.count(str))[n]
参数说明:
str: 表示为分隔符,默认为空格,但是不能为空(’’)。若字符串中没有分隔符,则把整个字符串作为列表的一个元素
num:表示分割次数。如果存在参数num,则仅分隔成 num+1 个子字符串,并且每一个子字符串可以赋给新的变量
[n]: 表示选取第n个分片
注意:当使用空格作为分隔符时,对于中间为空的项会自动忽略
Python3.8.3
import re#正则
import arrow#时间处理
import datetime#时间处理
from prettytable import PrettyTable#生成表格美化输出
# 添加文件
log_file = '网站访问日志.txt'
def get_file():
with open(log_file, 'r', encoding='UTF-8') as f: while True:
data = f.readline()
if data:
yield data
else:
break
# TODO:1:统计网站访问日志文件的总pv,uv
def log_total():
print("网站访问日志分析的总pv(页面访问量),uv(独立用户)".center(50, "-"))
tmp_dict = {
'pv': [], 'uv': set()}# 集合自动去重,优化了代码
print('waiting....')
for i in get_file():
res = re.findall('(\d+.\d+.\d+.\d+)\s-\s-\s',i)
if not res: continue
res = res[0]
tmp_dict['pv'].append(res)
tmp_dict['uv'].add(res)
table = PrettyTable(['总PV数','总uv数'])
table.add_row([len(tmp_dict['pv']),len(tmp_dict['uv'])])
print(table)
1:首先读取数据
2:通过正则匹配数据
3:网页访问量的统计事项:将ip存储进列表里
4:用户总数统计事项:将ip存储在集合中,利用集合自动去重的功能实现存储
5:通过PrettyTable模块实现格式化输出
# TODO:2:列出全天每小时的pv,uv数
def log_hour():
tmp_dict = {
}
print('waiting...')
for i in get_file():
res1 = re.search('(\[.*?\])', i)
if not res1:continue
res1 = res1.group().strip('[').strip(']') # 15/Apr/2019:00:00:01 +0800
tmp_str = datetime.datetime.strptime(res1.split(' ')[0], '%d/%b/%Y:%H:%M:%S') # 2019-04-15 00:00:01
tmp_day = arrow.get(tmp_str).strftime('%Y-%m-%d') # 2019-04-15
tmp_hour = arrow.get(tmp_str).strftime('%Y-%m-%d %H') # 2019-04-15 00
res2 = re.search('(\d+.\d+.\d+.\d+)\s-\s-\s', i)
if not res2:continue
if not tmp_dict.get(tmp_day):
tmp_dict[tmp_day] = {
}
if tmp_hour not in tmp_dict.get(tmp_day):
tmp_dict[tmp_day][tmp_hour] = {
"pv": [], "uv": set()}
tmp_dict[tmp_day][tmp_hour]['uv'].add(res2.group())
tmp_dict[tmp_day][tmp_hour]['pv'].append(res2.group())
for k in tmp_dict:
print('[{}]日的每小时的pv和uv数统计如下: '.format(k))
table = PrettyTable(["时间", '每个小时的pv数', '每个小时的uv数'])
for j, v in tmp_dict[k].items():
table.add_row([j, len(v['pv']), len(v['uv'])])
print(table)
1:首先读取数据
2:通过正则匹配数据
3:将数据格式化存储到字典里#
“2019-4-14”:{# “2019-4-14 00”: {“pv”: [], “uv”: set()},
4:最后将数据统计出来
# TODO:3:列出top 10 uv(独立用户)的IP地址,以及每个ip的pv点击数
def top_ten_uv():
tmp_dict = {
}
print("waiting.....")
for i in get_file(): # 循环每一行
res = re.search('(\d+.\d+.\d+.\d+)', i)
if not res: continue
res = res.group()
if res in tmp_dict:
tmp_dict[res]+=1
else:
tmp_dict[res] = 1
table = PrettyTable(['top10 uv的IP','top10 uv的ip的pv'])
tmp_list = sorted(tmp_dict.items(),key=lambda x: x[1],reverse=True)[0:10]
for n1,n2 in tmp_list:
table.add_row([n1,n2])
print(table)
1:首先读取数据
2:通过正则匹配数据
3:通过group返回匹配到的结果
4:将ip地池存储到字典里并且判断字典里是否已经存在,如果已经存在了键值加一,不存在则添加
5:输出数据
# 4:TODO :列出top 10访问量最多的页面及每个页面的访问量
def top_ten_visit():
tmp_dict = {
}
for i in get_file():
res = re.search(
'(?P((([01]{
0,1}\d{
0,1}\d|2[0-4]\d|25[0-5])\.){
3}([01]{
0,1}\d{
0,1}\d|2[0-4]\d|25[0-5]))).*(?P /.*?HTTP/1.1)' ,
i)
if not res:continue
ip, page = res.group("ip"), res.group("page").strip('HTTP/1.1')
if page in tmp_dict:
tmp_dict[page].append(ip)
else:
tmp_dict[page] = [ip]
table = PrettyTable(['top10的页面', 'top10的页面访问量'])
tmp_list = sorted(tmp_dict.items(), key=lambda x: len(x[1]), reverse=True)[0:10]
for n1, n2 in tmp_list:
table.add_row([ n1,len(n2)])
print(table)
1:首先读取数据
2:通过正则匹配数据
3:匹配网页的同时需要匹配好ip如果没有ip则不计入数据
4:将ip与page分组,并将page后面的HTTP/1.1strip掉
5:判断page是否在字典里不在的话添加,并肩ip添加进去,在的话直接添加值ip,字典没有值去重功能
6:循环自动匹配键与值输出:取出字典里的键,并输出值的长度
# 5:TODO:列出访问来源的设备列表及每个设备的访问量
def device_list():
print("waiting.....")
tmp_dict = {
}
for i in get_file():
res = re.search(
'(?P((([01]{
0,1}\d{
0,1}\d|2[0-4]\d|25[0-5])\.){
3}([01]{
0,1}\d{
0,1}\d|2[0-4]\d|25[0-5]))).*?(?P\(.*?\))' ,
i)
if not res:continue
ip, device = res.group("ip"), res.group("equipment")
if device in tmp_dict:
tmp_dict[device].append(ip)
else:
tmp_dict[device] = [ip]
table = PrettyTable(['设备来源','访问量'])
tmp_list = sorted(tmp_dict.items(), key=lambda x: len(x[1]), reverse=True)
for n1, n2 in tmp_list:
table.add_row([ n1,len(n2)])
print(table)
1:首先读取数据
2:通过正则匹配数据
3:匹配设备的同时需要匹配好ip如果没有ip则不计入数据
4:将设备与ip分组,分别加到字典里,设备是键,ip是值
5:输出:键:设备名,值:ip的长度
# TODO :退出系统
def q():
"""
退出
:return:
"""
exit("欢迎再次使用!!!")
退出系统
#TODO:功能循环
def handler():
tmp_dict = {
"1": ["统计本日志文件的总pv、uv", log_total],
"2": ["列出全天每小时的pv、uv数", log_hour],
"3": ["列出top 10 uv的IP地址,以及每个ip的pv点击数", top_ten_uv],
"4": ["列出top 10 访问量最多的页面及每个页面的访问量", top_ten_visit],
"5": ["列出访问来源的设备列表及每个设备的访问量", device_list],
"6": ["退出", q]
}
while True:
print("欢迎使用网站访问数据分析系统".center(50,'-'))
for k,v in tmp_dict.items():
print(k,v[0])
cmd = input('输入序号:').strip()
if cmd.upper() == 'q'or cmd.upper()=='Q':
break
if cmd in tmp_dict:
tmp_dict[cmd][-1]()
else:
print('输入不合法,请重新输入!!!!')
1:输入数字,对应功能能循环调用
2:判断输入数字是否在字典里,在字典内就直接调用函数,不在的话就重新输入
#TODO:函数调用
if __name__ == "__main__":
handler()