现在的位置: 首页 > 综合 > 正文

python分析apache日志的脚本

2013年09月22日 ⁄ 综合 ⁄ 共 4243字 ⁄ 字号 评论关闭

核心的正则模块是直接从apachelog模块里拿出来的,我自己几乎什么都没做
apahelog模块地址:http://pypi.python.org/pypi/apachelog/1.0

  1. #!/usr/bin/env python
  2. #coding=gbk
  3. """
  4. Apache Log Parser,
  5. see module apahcelog:
  6.     http://pypi.python.org/pypi/apachelog/1.0
  7. """
  8. import re
  9. import sys
  10. import ConfigParser
  11.  
  12. def getFormat():
  13.     # get ‘format’ from format.ini
  14.     config = ConfigParser.ConfigParser()
  15.     try:
  16.         inifh = open(format.ini)
  17.     except IOError:
  18.         print "Can not load format.ini !"
  19.         sys.exit(1)
  20.     config.readfp(inifh)
  21.     formatName =
  22.     format = {}
  23.     try:
  24.         formatName = config.get(type,name)
  25.     except ConfigParser.NoOptionError:
  26.         print "Bad section/option name! Please check format.ini"
  27.         sys.exit(1)
  28.     try:
  29.         options = config.options(format)
  30.     except ConfigParser.NoOptionError:
  31.         print "Can not enum option [format]"
  32.         sys.exit(1)
  33.     for opt in options:
  34.         if opt not in format.keys():
  35.             format[opt] = config.get(format,opt)
  36.         else:
  37.             print "duplicate name in option [format]"
  38.             sys.exit(1)
  39.     try:
  40.         ret = format[formatName]
  41.     except KeyError:
  42.         print "Format /"%s/" has not been defined in format.ini" %formatName
  43.         sys.exit(1)
  44.     return ret
  45. # intercept from module apachelog
  46. class ApacheLogParserError(Exception):
  47.     pass
  48. class parser():
  49.    
  50.     def __init__(self, format):
  51.         self._names = []
  52.         self._regex = None
  53.         self._pattern =
  54.         self._parse_format(format)
  55.    
  56.     def _parse_format(self, format):
  57.         format = format.strip()
  58.         format = re.sub([ /t]+, ,format)
  59.        
  60.         subpatterns = []
  61.  
  62.         findquotes = re.compile(r^//")
  63.         findreferreragent = re.compile(Referer|User-Agent)
  64.         findpercent = re.compile(^%.*t$)
  65.         lstripquotes = re.compile(r^//")
  66.         rstripquotes = re.compile(r//"$)
  67.        
  68.        
  69.         for element in format.split( ):
  70.  
  71.             hasquotes = 0
  72.             if findquotes.search(element): hasquotes = 1
  73.  
  74.             if hasquotes:
  75.                 element = lstripquotes.sub(, element)
  76.                 element = rstripquotes.sub(, element)
  77.            
  78.             self._names.append(self.alias(element))
  79.            
  80.             subpattern = (/S*)
  81.            
  82.             if hasquotes:
  83.                 if element == %r or findreferreragent.search(element):
  84.                     subpattern = r/"([^"//]*(?://.[^"//]*)*)/"
  85.                 else:
  86.                     subpattern = r/"([^/"]*)/"
  87.                
  88.             elif findpercent.search(element):
  89.                 subpattern = r(/[[^/]]+/])
  90.                
  91.             elif element == %U:
  92.                 subpattern = (.+?)
  93.            
  94.             subpatterns.append(subpattern)
  95.        
  96.         self._pattern = ^ +  .join(subpatterns) + $
  97.         try:
  98.             self._regex = re.compile(self._pattern)
  99.         except Exception, e:
  100.             raise ApacheLogParserError(e)
  101.        
  102.     def parse(self, line):
  103.         line = line.strip()
  104.         match = self._regex.match(line)
  105.        
  106.         if match:
  107.             data = {}
  108.             for k, v in zip(self._names, match.groups()):
  109.                 data[k] = v
  110.             return data
  111.        
  112.         raise ApacheLogParserError("Unable to parse: %s" % line)
  113.  
  114.     def alias(self, name):
  115.         return name

上面是我修改的模块内容,去除了一些用不到的东西,加了个配置文件,定义为AccessLog.py

  1. #!/usr/bin/env python
  2. # coding=gbk
  3. # author : Python[AT]Live.it
  4. import re
  5. import sys
  6. import AccessParse
  7.  
  8. try:
  9.     LogFile = sys.argv[1]
  10. except IndexError:
  11.     print "Usage : Python %s access.log" %sys.argv[0]
  12.     sys.exit(0)
  13. LogFormat = {
  14.         %h:Remote-IP,
  15.         %l:Login,
  16.         %u:User,
  17.         %t:AccessTime,
  18.         %r:Request,
  19.         %>s:Status,
  20.         %b:Bytes,
  21.         %{Referer}i:Referer,
  22.         %{User-Agent}i:User-Agent
  23.     }
  24. class myParser(AccessParse.parser):
  25.     def __init__(self,format):
  26.         AccessParse.parser.__init__(self,format)
  27.     def alias(self, name):
  28.         return LogFormat[name]
  29.  
  30. p = myParser(AccessParse.getFormat())
  31. for line in open(LogFile):
  32.     try:
  33.         data = p.parse(line)
  34.         print data
  35.     except AccessParse.ApacheLogParserError,e:
  36.         print "Parser Error , %s" %e
  37.         print "/nMaybe got a bad format in format.ini"
  38.         sys.exit(1)

然后定义一个format.ini

  1. [type]
  2. name = combined
  3. [format]
  4. common = %h %l %u %t /"%r/" %>s %b
  5. combined = %h %l %u %t /"%r/" %>s %b /"%{Referer}i/" /"%{User-Agent}i/"

这里指明要分析combined格式脚本,如果需要添加其他格式的话,在ini里继续添加,不过加的内容多的话,恐怕LogFromat字典还要改一下,那个字典不全,或是直接不用它也好,目前是字典内容直接打印出来的,可以根据需要匹配一下

E:/ApacheLogParser>python LogParser.py access.log

{’Status’: ‘301′, ‘Remote-IP’: ‘127.0.0.1′, ‘Bytes’: ‘235′, ‘AccessTime’: ‘[03/Jun/2009:10:53:19 +0800]‘, ‘Request’: ‘POST /wordpress HTTP/1.1′, ‘User-Agent’: “PySpider/1.0 (Python’s Spider | Python[AT]Live.it)”, ‘Referer’: ‘-’, ‘User’: ‘-’, ‘Login’: ‘-’}

最后,关于apache日志的一些正则,最原汁的在这里:

http://cpan.uwinnipeg.ca/htdocs/Apache-LogRegex/Apache/LogRegex.html

apachelog模块的作者也是参照这个写的

记录一下几个模块
apachelog (python)
Apache::LogRegex (perl)
Parse::AccessLogEntry (perl)

抱歉!评论已关闭.