Python解析nginx日志文件


Posted in Python onMay 11, 2015

项目的一个需求是解析nginx的日志文件。
简单的整理如下:

日志规则描述

首先要明确自己的Nginx的日志格式,这里采用默认Nginx日志格式:

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
          '$status $body_bytes_sent "$http_referer" '
          '"$http_user_agent" "$http_x_forwarded_for"';

其中一条真实记录样例如下:

172.22.8.207 - - [16/Dec/2014:17:57:35 +0800] "GET /report?DOmjjuS6keWJp+WculSQAgdUkAIPODExMzAwMDJDN0FC HTTP/1.1" 200 0 "-" "XXXXXXX/1.0.16; iPhone/iOS 8.1.2; ; 8DA77E2F91D0"

其中,客户端型号信息用XXXXXXX代替。

项目中已经按照业务规则对Nginx日志文件进行了处理命名规则如下:

ID-ID-YYMMDD-hhmmss
并且所有的日志文件存放在统一路径下。

解决思路

获取所有日志文件path

这里使用Python的glob模块来获取日志文件path

import glob
def readfile(path):
  return glob.glob(path + '*-*-*-*')

获取日志文件中每一行的内容

使用Python的linecache模块来获取文件行的内容

import linecache


def readline(path):
  return linecache.getlines(path)

注意:linecache模块使用了缓存,所以存在以下问题:

在使用linecache模块读取文件内容以后,如果文件发生了变化,那么需要使用linecache.updatecache(filename)来更新缓存,以获取最新变化。

linecache模块使用缓存,所以会耗费内存,耗费量与要解析的文件相关。最好在使用完毕后执行linecache.clearcache()清空一下缓存。

当然,作为优化,这里可以利用生成器来进行优化。暂且按下不表。

处理日志条目

一条日志信息就是一个特定格式的字符串,因此使用正则表达式来解析,这里使用Python的re模块。
下面,一条一条建立规则:

规则

ip = r"?P<ip>[\d.]*"
  date = r"?P<date>\d+"
  month = r"?P<month>\w+"
  year = r"?P<year>\d+"
  log_time = r"?P<time>\S+"
  method = r"?P<method>\S+"
  request = r"?P<request>\S+"
  status = r"?P<status>\d+"
  bodyBytesSent = r"?P<bodyBytesSent>\d+"
  refer = r"""?P<refer>
       [^\"]*
       """
  userAgent=r"""?P<userAgent>
        .*
        """

解析

p = re.compile(r"(%s)\ -\ -\ \[(%s)/(%s)/(%s)\:(%s)\ [\S]+\]\ \"(%s)?[\s]?(%s)?.*?\"\ (%s)\ (%s)\ \"(%s)\"\ \"(%s).*?\"" %( ip, date, month, year, log_time, method, request, status, bodyBytesSent, refer, userAgent ), re.VERBOSE)

m = re.findall(p, logline)

这样,就可以得到日志条目中各个要素的原始数据。

格式及内容转化

得到日志原始数据之后,需要根据业务要求,对原始数据进行格式及内容转化。
这里需要处理的内容包括:时间,request,userAgent

时间格式转化

在日志信息原始数据中存在Dec这样的信息,利用Python的time模块可以方便的进行解析

import time
def parsetime(date, month, year, log_time):
  time_str = '%s%s%s %s' %(year, month, date, log_time)
  return time.strptime(time_str, '%Y%b%d %H:%M:%S')

解析request

在日志信息原始数据中得到的request的内容格式为:

/report?XXXXXX
这里只需要根据协议取出XXXXXX即可。
这里仍然采用Python的re模块

import re
def parserequest(rqst):
  param = r"?P<param>.*"
  p = re.compile(r"/report\?(%s)" %param, re.VERBOSE)
  return re.findall(p, rqst)

接下来需要根据业务协议解析参数内容。这里需要先利用base64模块解码,然后再利用struct模块解构内容:

import struct
import base64
def parseparam(param):
  decodeinfo = base64.b64decode(param)
  s = struct.Struct('!x' + bytes(len(decodeinfo) - (1 + 4 + 4 + 12)) + 'xii12x')
  return s.unpack(decodeinfo)

解析userAgent

在日志信息原始数据中userAgent数据的格式为:

XXX; XXX; XXX; XXX
根据业务要求,只需要取出最后一项即可。
这里采用re模块来解析。

import re
def parseuseragent(useragent):
  agent = r"?P<agent>.*"
  p = re.compile(r".*;.*;.*;(%s)" %agent, re.VERBOSE)
  return re.findall(p, useragent)

至此,nginx日志文件解析基本完成。
剩下的工作就是根据业务需要,对获得的基本信息进行处理。

以上所述就是本文的全部内容了,希望大家能够喜欢。

Python 相关文章推荐
python实现下载文件的三种方法
Feb 09 Python
python版学生管理系统
Jan 10 Python
python通过百度地图API获取某地址的经纬度详解
Jan 28 Python
Numpy截取指定范围内的数据方法
Nov 14 Python
django将网络中的图片,保存成model中的ImageField的实例
Aug 07 Python
python生成器用法实例详解
Nov 22 Python
Django3.0 异步通信初体验(小结)
Dec 04 Python
Python Socketserver实现FTP文件上传下载代码实例
Mar 27 Python
python爬虫实例之获取动漫截图
May 31 Python
python 8种必备的gui库
Aug 27 Python
史上最详细的Python打包成exe文件教程
Jan 17 Python
Python Selenium操作Cookie的实例方法
Feb 28 Python
Python字符串替换实例分析
May 11 #Python
Python使用django获取用户IP地址的方法
May 11 #Python
总结Python编程中三条常用的技巧
May 11 #Python
python求解水仙花数的方法
May 11 #Python
pymongo为mongodb数据库添加索引的方法
May 11 #Python
python判断windows系统是32位还是64位的方法
May 11 #Python
Python中使用装饰器时需要注意的一些问题
May 11 #Python
You might like
php实现mysql数据库备份类
2008/03/20 PHP
PHP学习笔记之数组篇
2011/06/28 PHP
PHP多个版本的分析解释
2011/07/21 PHP
PHP写的加密函数,支持私人密钥(详细介绍)
2013/06/09 PHP
利用php下载xls文件(自己动手写的)
2014/04/18 PHP
ThinkPHP中关联查询实例
2014/12/02 PHP
通过PHP的Wrapper无缝迁移原有项目到新服务的实现方法
2020/04/02 PHP
Yii框架多语言站点配置方法分析【中文/英文切换站点】
2020/04/07 PHP
javascript应用:Iframe自适应其加载的内容高度
2007/04/10 Javascript
jQuery使用fadein方法实现渐出效果实例
2015/03/27 Javascript
JavaScript中操作Mysql数据库实例
2015/04/02 Javascript
JavaScript实现的encode64加密算法实例分析
2015/04/15 Javascript
浅谈javascript的Touch事件
2015/09/27 Javascript
关于获取DIV内部内容报错的原因分析及解决办法
2016/01/29 Javascript
javascript点击按钮实现隐藏显示切换效果
2016/02/03 Javascript
KnockoutJS 3.X API 第四章之表单submit、enable、disable绑定
2016/10/10 Javascript
JS制作适用于手机和电脑的通知信息效果
2016/10/28 Javascript
BootStrap表单控件之文本域textarea
2017/05/23 Javascript
Node 搭建一个静态资源服务器的实现
2019/05/20 Javascript
JS实现纵向轮播图(初级版)
2020/01/18 Javascript
vue项目,代码提交至码云,iconfont的用法说明
2020/07/30 Javascript
[00:32]2018DOTA2亚洲邀请赛出场——LGD
2018/04/04 DOTA
[01:00:12]2018DOTA2亚洲邀请赛 4.7 淘汰赛 VP vs LGD 第一场
2018/04/09 DOTA
[49:59]KG vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python中使用摄像头实现简单的延时摄影技术
2015/03/27 Python
Python远程桌面协议RDPY安装使用介绍
2015/04/15 Python
Python导出数据到Excel可读取的CSV文件的方法
2015/05/12 Python
Python的Django REST框架中的序列化及请求和返回
2016/04/11 Python
Python正则表达式实现截取成对括号的方法
2017/01/06 Python
Python中格式化format()方法详解
2017/04/01 Python
PyQt5实现下载进度条效果
2018/04/19 Python
python的set处理二维数组转一维数组的方法示例
2019/05/31 Python
Html5游戏开发之乒乓Ping Pong游戏示例(三)
2013/01/21 HTML / CSS
祖国在我心中演讲稿500字
2014/05/04 职场文书
工商干部先进事迹
2014/05/14 职场文书
运动会主持人开幕词
2016/03/04 职场文书