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()