发表于: 2018-01-24 00:55:22
4 1088
今天完成的事情:开始着手准备、分析与解决“任务1”的相关内容
1、任务内容
使用 Python 访问 Nginx 日志,统计每一个请求的访问次数,并且每天自动发邮件告知前十个请求。
2、任务分解
(1)需要Nginx日志文件一份,尽量搞清楚其日志格式;
(2)打开日志文件,获取日志每行内容;
(3)对每行日志内容格式经过分析后,使用相关技术手段采集到每个请求的IP地址(这里应该需要使用 re 正则表达式这个工具);
(4)将采集到的IP地址保存到某个容器中(最常见的容器有List列表、Tuple元组、Set集合、Dict字典、File文件等);
(5)统计容器中的相同IP地址的个数(也就是某个IP地址在容器中共有多少个,这里应该有技术难度);
(6)这里有疑点:任务内容中的“前十个请求”是指什么呢?按照每个请求的时间顺序?还是按照每个请求的次数多少?我的理解是,根据前面的统计IP次数这个任务,因此这“前十个请求”应该是指按照次数的多少排序,排在最前面的十个IP请求。那么,这里需要实现对对应IP地址的个数进行排序操作;
(7)需要具备发送Email邮件功能。
3、Nginx 日志格式
Nginx 的 log 日志分为 access log 和 error log 两类,这里暂按 access log 为样本。格式如下:
192.168.68.62 - - [23/Jan/2018:13:36:41 +0800] "GET /general/ipanel/user/user_count.php?CHECK_SMS=1&CLIENT=2&_=1514353004443 HTTP/1.1" 200 237 "http://192.168.1.18/ispirit/index.php?I_VER=2" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.138 Safari/537.36" "-"
192.168.50.5 - - [23/Jan/2018:13:36:41 +0800] "GET /ispirit/im/count.php?TYPE=email,sms,taskcenter,sns HTTP/1.1" 200 17 "-" "ispiritPro" "-"
192.168.10.211 - - [23/Jan/2018:13:36:44 +0800] "GET /general/ipanel/user/user_count.php?CHECK_SMS=1&CLIENT=2&_=1514353132409 HTTP/1.1" 200 237 "http://192.168.1.18/ispirit/index.php?I_VER=2" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.138 Safari/537.36" "-"
192.168.90.226 - - [23/Jan/2018:13:36:45 +0800] "GET /ispirit/im/count.php?TYPE=email,sms,taskcenter,sns HTTP/1.1" 200 18 "-" "ispiritPro" "-"
从上面的每行日志,我们可以看出包含以下几部分信息:
1.客户端(用户)IP地址。如:上例中的每行开始部分的内容 192.168.68.622.访问时间。如:上例中的 [23/Jan/2018:13:36:41 +0800]
3.请求方式(GET/POST)。如:上例中的"GET /general/ipanel/user/user_count.php?CHECK_SMS=1&CLIENT=2&_=1514353004443 HTTP/1.1"
4.请求状态。如上例中的 200
5.请求页面大小,默认为B(byte)。如:上例中的 237
6.来源页面,即从哪个页面转到本页。如:上例中的 "http://192.168.1.18/ispirit/index.php?I_VER=2"
7.用户浏览器信息。如:上例中的 "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.138 Safari/537.36"
显然,每行日志的开头部分即为需要采集的IP请求地址。
4、解决思路
为方便起见,将生产环境中的Nginx日志文件复制一份到当前脚本目录中,使用上一日报中有关文件操作的相关知识来打开文件并遍历读取每行日志内容,对每行日志内容通过构建符合条件的正则表达式进行匹配,将匹配到的IP结果添加到某个List列表中。最后对列表中的IP进行统计,这里可以借助 Python的内置标准库 collections 中的 Counter 类进行统计 List 中的相同元素的个数。
一个简单用法如下:
from collections import Counter
list = ['a', 'c', 'b', 'c', 'c', 'b', 'd', 'c', 'a', 'b']
list_count = Counter(list)
print(list_count)
运行结果如下:
Counter({'c': 4, 'b': 3, 'a': 2, 'd': 1})
从运行结果可以发现,list 列表中的每个元素 a、b、c、d 的个数已经统计出来了,形成键值对 'c':4 保存在Counter类中了。而且,神奇的是,这个键值对还是已经按照“值”的大小进行了排序的。这个功能居然恰好完成了我们第(6)个小任务的代码功能!实在是强大啊!
5、代码实现
# coding=utf-8
import re
from collections import Counter
import smtplibfrom email.mime.text import MIMEText
ip_list = []
content = ""
with open(r"D:\PycharmProjects\PyCode\Test.access.20180123.log", 'r') as f:
for line in f:
ip = re.search(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', line)
if ip is not None:
ip_list.append(ip.group())
ip_counter = Counter(ip_list)
for item in ip_counter.most_common(10):content += "IP 地址:%s,访问次数:%d; " % (item[0], item[1]) # 正文
msg_from = 'swxxswxx@qq.com' # 发送方邮箱
passwd = 'xxxxxxxxxxxxxx' # 填入发送方邮箱的授权码
msg_to = '693534431@qq.com' # 收件人邮箱
subject = "Ngnix日志前十请求信息" # 主题
msg = MIMEText(content)
msg['Subject'] = subject
msg['From'] = msg_from
msg['To'] = msg_to
try:
s = smtplib.SMTP_SSL("smtp.qq.com", 465) # 邮件服务器及端口号
s.login(msg_from, passwd)
s.sendmail(msg_from, msg_to, msg.as_string())
print("邮件发送成功")
except:
print("Error: 无法发送邮件")
finally:
s.quit()
6、邮件截图
评论