作业简介:
- 利用正则表达式,解析网站日志数据,并返回数据。
1.作业里的名词:
2.作业需求:
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就算一个独立用户
3.日志格式:
4.作业思路:
- 1.运行主函数main(),调用数据处理函数data_processing(data)
- 2.数据处理函数data_processing(data),调用四个对应的数据筛选函数
- 3.对应的四个数据清洗函数返回数据
- 4.数据处理函数,整理数据输出信息
5.正则表达式:
提取ip:re.findall("\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}.-", data)
提取时间:re.findall("\d{2}/\D{3}/\d{4}:\d{2}:\d{2}", data)
提取url:re.findall("\w+ /.HTTP/\d.\d", data)
提取设备名称:re.findall("Mozilla/.", data)
6.思维导图:
7.支持输入编号查询:
msg = “”"
1–>查看总pv、uv,
2–>查看全天每小时的pv、uv数,
3–>查看top 10 uv的IP地址,以及每个ip的pv点击数,
4–>查看top 10 访问量最多的页面及每个页面的访问量,
5–>查看访问来源、设备的访问量,
6–>输入 “q” 退出程序"""
8.作业源码:
#!/usr/bin/python
# -*- coding:utf-8 -*-
# python就业班:HuangPei
# date_time:2020/12/07
"""
作业需求:
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就算一个独立用户
编码规范需求:10%
1. 代码规范遵守pep8 (https://python.org/dev/peps/pep-0008/)
2. 函数有相应的注释
3. 程序有文档说明文件(README.md)
4. 程序的说明文档必须包含的内容:程序的实现的功能、程序的启动方式、登录用户信息、程序的运行效果
5. 程序设计的流程图:
"""
import re
FILE_PATH = './网站访问日志.txt'
# 读取数据
def read_data(path):
"""
读取TXT内容
:param path:
:return:
"""
with open(path, 'r', encoding='utf-8') as f:
return f.read()
head_data = read_data(FILE_PATH)
# print(type(head_data))
# 提取访问源(IP)
def access_source(data):
"""
返回IP列表
:param data:
:return:
"""
# re.findall 把所有匹配到的字符放到列表中,返回一个列表
# ip_data = re.findall("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|-", data)
ip_data = re.findall("\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}.-", data)
return ip_data
# 提取访问时间
def access_time(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)
return time_data
# 提取访问的url页面
def access_url(data):
"""
回返访问设备。
:param data:
:return:
"""
url_data = re.findall("\\w+ /.*HTTP/\\d.\\d", data)
return url_data
# 提取访问的设备
def access_equipment(data):
"""
返回设备数据
:param data:
:return:
"""
equipment_data = re.findall("Mozilla/.*", data)
return equipment_data
# 数据处理函数
def data_processing(data):
"""
处理总pv、uv
处理全天每小时的pv、uv数
处理top 10 uv的IP地址,以及每个ip的pv点击数
处理top 10 访问量最多的页面及每个页面的访问量
处理访问来源的设备列表及每个设备的访问量
:return:
"""
print("正在加载数据~~~~")
msg = """
1-->查看总pv、uv,
2-->查看全天每小时的pv、uv数,
3-->查看top 10 uv的IP地址,以及每个ip的pv点击数,
4-->查看top 10 访问量最多的页面及每个页面的访问量,
5-->查看访问来源、设备的访问量,
6-->输入 "q" 退出程序"""
day_ip = {} # 存全天每小时的ip
day_source = {} # 存全天每小时的source(访问量)
click_pv = {} # 存ip点击的页面
ip = access_source(data)
url = access_url(data)
time_list = access_time(data)
equipment = access_equipment(data)
for ip_data in set(ip):
day_ip[ip.count(ip_data)] = ip_data # count返回这个值出现过几次
for source_data in set(time_list):
day_source[time_list.count(source_data)] = source_data
for top_source in set(url):
click_pv[url.count(top_source)] = top_source
equipment_data = dict(zip(equipment, url))
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
print("总的页面访问量:%s 次" % (len(url)))
print("总的IP数量:%s 个" % (len(set(ip)))) # set去重
elif cmd == 2:
# 2.列出全天每小时的pv、uv数
# ip数量提取
print("2.全天每小时的pv、uv数")
for hours_ip in sorted(day_ip.keys(), reverse=True)[0:10]:
print("每小时的ip数量:%s ip:%s" % (hours_ip, day_ip[hours_ip]))
# 访问量提取
# print(day_source)
for hours_source in sorted(day_source.keys(), reverse=True)[0:10]:
print("每个小时的访问量:%s次 时间: %s" % (hours_source, day_source[hours_source]))
elif cmd == 3:
# 3.列出top 10 uv的IP地址,以及每个ip的pv点击数
print("3.top 10 的ip地址")
for top_ip in sorted(day_ip.keys(), reverse=True)[0:10]:
print("top 10的pv点击数:%s次,ip地址 %s" % (top_ip, day_ip[top_ip]))
print("每个ip的页面点击数")
for click_data in sorted(click_pv.keys(), reverse=True)[0:10]:
print("top 10的页面访问量:%s次 --> %s" % (click_data, click_pv[click_data]))
elif cmd == 4:
# 4.列出top 10 访问量最多的页面及每个页面的访问量
print("4.访问量最多的页面+访问量")
for click_data in sorted(click_pv.keys(), reverse=True)[0:10]:
print("top 10的访问量最多的页面:%s 页面访问量:%s" % (click_pv[click_data], click_data))
elif cmd == 5:
# 5.列出访问来源的设备列表及每个设备的访问量
print("5.设备来源和设备访问量---")
count = 0
for equipment_source, equipment_amount in equipment_data.items():
print("设备访问量:%s 设备名称:%s " % (len(equipment_amount), equipment_source))
if count == 10:break
count += 1
elif cmd == 'q':quit()
else:
print("请重新输入~~")
# 主函数
def main():
"""
程序入口
:return:
"""
data_processing(head_data)
main()
总结:
这个作业可以很好的练习正则表达式,当然也可以用其他来方法实现,用正则实现,开发速度是最快的,但是也带来了一个问题,筛选数据会很慢,这个作业还有许多地方要优化,今天分享给小伙伴们,希望对你们有帮助。