python 高速处理分析超大网站日志文件 带进度条手动输入日志文件
python 高速处理分析超大网站日志文件 带进度条手动输入日志文件
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就算一个独立用户
#!/usr/bin/python
# -*- coding:utf-8 -*-
# date_time:2021/6/16
"""
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就算一个独立用户
"""
import re
from tqdm import tqdm
import time
class log_analysis():
def __init__(self):
self.ip = {} #所有ip
self.url = {} #所有url
self.day_ip = {} # 存全天每小时的ip
self.day_source = {} # 存全天每小时的source(访问量)
self.click_pv = {} # 存ip点击的页面
self.equipment_data = {} # 返回设备数据
# 读取数据
def read_data(self,path):
"""
带进度条读取日志内容
:param path:
:return:
"""
print("正在读取数据,请稍候~~~~")
num_lines = sum(1 for line in open(path,'r', encoding='utf-8'))
with open(path, 'r', encoding='utf-8') as f:
#lines = "";
for line in tqdm(f, total=num_lines):
#lines = lines+line
self.format_data(line)
#格式化数据
def format_data(self,data):
ip = self.access_source(data)
url = self.access_url(data)
time_list = self.access_time(data)
equipment = self.access_equipment(data)
for ip_data in set(ip):
self.ip[ip_data]=ip_data
self.day_ip.setdefault(ip_data,0)
self.day_ip[ip_data] +=1 # count返回这个值出现过几次
for source_data in set(time_list):
self.day_source.setdefault(source_data,0)
self.day_source[source_data] += 1
for top_source in set(url):
self.url.setdefault(top_source,0)
self.url[top_source] += 1
self.click_pv.setdefault(top_source,0)
self.click_pv[top_source] += 1
for equipment_source in set(equipment):
self.equipment_data.setdefault(equipment_source,0)
self.equipment_data[equipment_source] += 1
#self.equipment_data = dict(zip(equipment, url))
# 提取访问源(IP)
def access_source(self,data):
"""
返回IP列表
:param data:
:return:
"""
# re.findall 把所有匹配到的字符放到列表中,返回一个列表
ip_data = re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", data)
return ip_data
# 提取访问时间
def access_time(self,data):
"""
返回时间列表
:param data:
:return:
"""
# 这个匹配全时间,但是只要求到小时,用第二个匹配,不然统计访问量会运算很久
# time_data = re.findall("(?P<time>\\d{4}:\\d{2}.\\d{2}.\\d{2}.\\W.\\d{3})", data)
# time_data = re.findall("(?P<time>\\d{4}:\\d{2})", data)
time_data = re.findall("\d{2}/\D{3}/\d{4}:\d{2}:\d{2}", data)
#print(time_data)
# for time in time_data:
# time_list.append(time)
# print(len(time_list))
return time_data
# 提取访问的url页面
def access_url(self,data):
"""
回返访问设备。
:param data:
:return:
"""
url_data = re.findall("\\w+ /.*HTTP/\\d.\\d", data)
# for url in url_data:
# # print(type(url))
# if 'GET' or 'POST' not in str(url):
# url_list.append(url)
# # print(url)
# else:
# continue
# print(url_list)
return url_data
# 提取访问的设备
def access_equipment(self,data):
"""
返回设备数据
:param data:
:return:
"""
equipment_data = re.findall("Mozilla/.*", data)
# for equipment in equipment_data:
# equipment_list.append(equipment)
# print(equipment_list)
return equipment_data
# 数据处理函数
def data_processing(self):
"""
处理总pv、uv
处理全天每小时的pv、uv数
处理top 10 uv的IP地址,以及每个ip的pv点击数
处理top 10 访问量最多的页面及每个页面的访问量
处理访问来源的设备列表及每个设备的访问量
:return:
"""
msg = """
1-->查看总pv、uv,
2-->查看全天每小时的pv、uv数,
3-->查看top 10 uv的IP地址,以及每个ip的pv点击数,
4-->查看top 10 访问量最多的页面及每个页面的访问量,
5-->查看访问来源、设备的访问量,
6-->重新选择文件,
7-->输入 "q" 退出程序"""
ip = self.ip #所有ip
url = self.url #所有url
day_ip = self.day_ip # 存全天每小时的ip
day_source = self.day_source # 存全天每小时的source(访问量)
click_pv = self.click_pv # 存ip点击的页面
equipment_data = self.equipment_data # 返回设备数据
print("数据处理完成!!!")
while True:
print(msg)
user_input = input("请输入你先查询的信息编号:")
if not user_input:
print("请输入内容~~")
continue
cmd = int(user_input) if user_input.isdigit() else user_input
if cmd == 1:
# 1.统计本日志文件的总pv、uv
url_num = 0
for ip_data in set(url):
url_num +=url[ip_data]
print("总的页面访问量:%s 次" % url_num)
print("总的IP数量:%s 个" % (len(set(ip)))) # set去重
elif cmd == 2:
# 2.列出全天每小时的pv、uv数
# ip数量提取
print("2.全天每小时的pv、uv数")
for hours_ip,hours_num in sorted(day_ip.items(), key=lambda item:item[1], reverse=True)[0:10]:
print("每小时的ip数量:%s ip:%s" % (hours_num, hours_ip))
# 访问量提取
# print(day_source)
for hours_source,hours_num in sorted(day_source.items(), key=lambda item:item[1], reverse=True)[0:10]:
print("每个小时的访问量:%s次 时间: %s" % (hours_num, hours_source))
elif cmd == 3:
# 3.列出top 10 uv的IP地址,以及每个ip的pv点击数
print("3.top 10 的ip地址")
for top_ip,ip_num in sorted(day_ip.items(), key=lambda item:item[1], reverse=True)[0:10]:
print("top 10的pv点击数:%s次,ip地址 %s" % (ip_num, top_ip))
print("每个ip的页面点击数")
for click_data,click_num in sorted(click_pv.items(), key=lambda item:item[1], reverse=True)[0:10]:
print("top 10的页面访问量:%s次 --> %s" % (click_num, click_data))
elif cmd == 4:
# 4.列出top 10 访问量最多的页面及每个页面的访问量
print("4.访问量最多的页面+访问量")
for click_data,click_num in sorted(click_pv.items(), key=lambda item:item[1], reverse=True)[0:10]:
print("top 10的访问量最多的页面:%s 页面访问量:%s" % (click_num, click_data))
elif cmd == 5:
# 5.列出访问来源的设备列表及每个设备的访问量
print("5.设备来源和设备访问量---")
count = 0
for equipment_source,equipment_num in sorted(equipment_data.items(), key=lambda item:item[1], reverse=True)[0:10]:
print("设备访问量:%s 设备名称:%s " % (equipment_num, equipment_source))
if count == 10:break
count += 1
elif cmd == 6:
inputfile()
elif cmd == 'q':quit()
else:
print("请重新输入~~")
def inputfile():
file_input = input("请输入您要处理的日志文件:")
while True:
if not file_input:
print("请输入内容~~")
continue
print(file_input)
obj1 = log_analysis()
obj1.read_data(file_input)
obj1.data_processing()
# 主函数
def main():
"""
程序入口
:return:
"""
inputfile()
#data_processing(head_data)
main()

