Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 解析apache日志文件_Python_File Io - Fatal编程技术网

Python 解析apache日志文件

Python 解析apache日志文件,python,file-io,Python,File Io,我刚开始学习Python,想读一个Apache日志文件,并将每行的一部分放入不同的列表中 文件中的行 172.16.0.3--[25/Sep/2002:14:04:19+0200]“GET/HTTP/1.1”401-“Mozilla/5.0(X11;U;Linux i686;en-US;rv:1.1)Gecko/20020827” 根据格式是 %h%l%u%t\%r\“%>s%b\“%{Referer}i\“\”%{User Agent}i\ 我可以打开文件并按原样读取,但我不知道如何使其以那种

我刚开始学习Python,想读一个Apache日志文件,并将每行的一部分放入不同的列表中

文件中的行

172.16.0.3--[25/Sep/2002:14:04:19+0200]“GET/HTTP/1.1”401-“Mozilla/5.0(X11;U;Linux i686;en-US;rv:1.1)Gecko/20020827”

根据格式是

%h%l%u%t\%r\“%>s%b\“%{Referer}i\“\”%{User Agent}i\

我可以打开文件并按原样读取,但我不知道如何使其以那种格式读取,以便我可以将每个部分放入列表中。

这是我的工作

例如:

line = '172.16.0.3 - - [25/Sep/2002:14:04:19 +0200] "GET / HTTP/1.1" 401 - "" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.1) Gecko/20020827"'
regex = '([(\d\.)]+) - - \[(.*?)\] "(.*?)" (\d+) - "(.*?)" "(.*?)"'

import re
print re.match(regex, line).groups()
输出将是一个元组,其中包含来自该行的6条信息(特别是该模式中括号内的组):


使用正则表达式将行拆分为单独的“标记”:


另一个解决方案是使用专用工具,例如,

我创建了一个python库,它可以做到这一点:

>导入apache\u日志\u解析器
>>>行\u parser=apache\u log\u parser.make\u parser(“%h%t%Dus\%r\”%>s%b\“%{Referer}i\”\“%{User Agent}i\%l%u”)
>>>log_line_data=line_解析器('127.0.0.1[16/Aug/2013:15:45:34+0000]1966093us“GET/HTTP/1.1”200 3478”https://example.com/“Mozilla/5.0(X11;U;Linux x86_64;en-US;rv:1.9.2.18)”——”
>>>pprint(日志行数据)
{'pid':'6113',
“远程_主机”:“127.0.0.1”,
“远程日志名”:“-”,
“远程用户”:“,
“请求第一行”:“GET/HTTP/1.1”,
“请求\头\引用者”:https://example.com/',
“请求头用户代理”:“Mozilla/5.0(X11;U;Linux x86;en-US;rv:1.9.2.18)”,
'响应字节数'clf':'3478',
“状态”:“200”,
“收到时间”:“[16/Aug/2013:15:45:34+0000]”,
《时代》:1966093}

考虑到格式的简单性,RegEx似乎极端且有问题,因此我编写了这个小拆分器,其他人可能也会发现它很有用:

def apache2_logrow(s):
    ''' Fast split on Apache2 log lines

    http://httpd.apache.org/docs/trunk/logs.html
    '''
    row = [ ]
    qe = qp = None # quote end character (qe) and quote parts (qp)
    for s in s.replace('\r','').replace('\n','').split(' '):
        if qp:
            qp.append(s)
        elif '' == s: # blanks
            row.append('')
        elif '"' == s[0]: # begin " quote "
            qp = [ s ]
            qe = '"'
        elif '[' == s[0]: # begin [ quote ]
            qp = [ s ]
            qe = ']'
        else:
            row.append(s)

        l = len(s)
        if l and qe == s[-1]: # end quote
            if l == 1 or s[-2] != '\\': # don't end on escaped quotes
                row.append(' '.join(qp)[1:-1].replace('\\'+qe, qe))
                qp = qe = None
    return row

将其添加到httpd.conf中,以将apache日志转换为json

LogFormat "{\"time\":\"%t\", \"remoteIP\" :\"%a\", \"host\": \"%V\", \"request_id\": \"%L\", \"request\":\"%U\", \"query\" : \"%q\", \"method\":\"%m\", \"status\":\"%>s\", \"userAgent\":\"%{User-agent}i\", \"referer\":\"%{Referer}i\" }" json_log

CustomLog /var/log/apache_access_log json_log
CustomLog "|/usr/bin/python -u apacheLogHandler.py" json_log
现在,您可以访问json格式的日志。 使用下面的python代码解析不断更新的json日志

apacheLogHandler.py

import time
f = open('apache_access_log.log', 'r')
for line in f: # read all lines already in the file
  print line.strip()

# keep waiting forever for more lines.
while True:
  line = f.readline() # just read more
  if line: # if you got something...
    print 'got data:', line.strip()
  time.sleep(1)
重新导入
主机=r'^(?P.*)'
空格=r'\s'
标识=r'\S+'
用户=r'\S+'
时间=r'(?P\[.*.\])'
请求=r'\'(?P.*?\“'
状态=r'(?P\d{3})'
大小=r'(?P\S+)
REGEX=主机+空间+标识+空间+用户+空间+时间+空间+请求+空间+状态+空间+大小+空间
def解析器(日志行):
匹配=重新搜索(正则表达式,日志行)
return((match.group('host'),
match.group('time'),
match.group('request'),
match.group('status'),
match.group('大小')
)
)
logLine=“”180.76.15.30---[24/Mar/2017:19:37:57+0000]“GET/shop/page/32/?count=15&orderby=title&add_to_wishlist=4846 HTTP/1.1“404 10202”-”Mozilla/5.0(兼容;Baiduspider/2.0+http://www.baidu.com/search/spider.html)"""
结果=分析器(logLine)
打印(结果)

您对该行的哪些元素感兴趣?(所有的?)当每一行都有细微的变化时,我希望它们能以准确的格式阅读:)你误解了-我的意思是,你想从每一行中提取什么?日期?知识产权?所有这些?你想改变apache日志文件存储的结构吗?@DavidRobinson我想把ip放在一个列表中,第一个“-”代表什么,第二个“-”是用户,所以它应该放在一个用户列表中,日期和时间放在另一个列表中等等。这看起来不错,但我能为每个部分都加上一个“regex”吗?类似这样的“ip=”([(\d\)]+)“date=”……“req=”………“')我想我已经弄明白了。谢谢!当我尝试文件中的其他行时,它不起作用。ex 127.0.0.1-stefan[01/Apr/2002:12:17:21+0200]“GET/sit3-shine.7.gif HTTP/1.1“200 15811”“”Mozilla/5.0(兼容;Konqueror/2.2.2-2;Linux)”@ogward:它不工作的一个原因是第二个破折号并不总是破折号——在这种情况下,它就是名字
stefan
。在模式中将其替换为
(.*)
。(文件中的行还有其他问题-我建议您熟悉regex,并且我相信您能够适应我的示例。实际上,这不是正则表达式的工作,因为请求中任何用户提供的行都可以包含空格或空格。)“这可能会中断您的解析。例如,如果有人连接到一个没有url逃逸空间的客户端,”。谁会做这样的事?黑客!很容易看出这种情况是如何发生的,只需使用telnet或netcat连接到端口80,并发出手动请求,如GET/dlkfj”lsakjdf HTTP/1.1这在Python3中对我有效。我在其他正则表达式示例中遇到了错误。谢谢。
def apache2_logrow(s):
    ''' Fast split on Apache2 log lines

    http://httpd.apache.org/docs/trunk/logs.html
    '''
    row = [ ]
    qe = qp = None # quote end character (qe) and quote parts (qp)
    for s in s.replace('\r','').replace('\n','').split(' '):
        if qp:
            qp.append(s)
        elif '' == s: # blanks
            row.append('')
        elif '"' == s[0]: # begin " quote "
            qp = [ s ]
            qe = '"'
        elif '[' == s[0]: # begin [ quote ]
            qp = [ s ]
            qe = ']'
        else:
            row.append(s)

        l = len(s)
        if l and qe == s[-1]: # end quote
            if l == 1 or s[-2] != '\\': # don't end on escaped quotes
                row.append(' '.join(qp)[1:-1].replace('\\'+qe, qe))
                qp = qe = None
    return row
LogFormat "{\"time\":\"%t\", \"remoteIP\" :\"%a\", \"host\": \"%V\", \"request_id\": \"%L\", \"request\":\"%U\", \"query\" : \"%q\", \"method\":\"%m\", \"status\":\"%>s\", \"userAgent\":\"%{User-agent}i\", \"referer\":\"%{Referer}i\" }" json_log

CustomLog /var/log/apache_access_log json_log
CustomLog "|/usr/bin/python -u apacheLogHandler.py" json_log
import time
f = open('apache_access_log.log', 'r')
for line in f: # read all lines already in the file
  print line.strip()

# keep waiting forever for more lines.
while True:
  line = f.readline() # just read more
  if line: # if you got something...
    print 'got data:', line.strip()
  time.sleep(1)
import re


HOST = r'^(?P<host>.*?)'
SPACE = r'\s'
IDENTITY = r'\S+'
USER = r'\S+'
TIME = r'(?P<time>\[.*?\])'
REQUEST = r'\"(?P<request>.*?)\"'
STATUS = r'(?P<status>\d{3})'
SIZE = r'(?P<size>\S+)'

REGEX = HOST+SPACE+IDENTITY+SPACE+USER+SPACE+TIME+SPACE+REQUEST+SPACE+STATUS+SPACE+SIZE+SPACE

def parser(log_line):
    match = re.search(REGEX,log_line)
    return ( (match.group('host'),
            match.group('time'), 
                      match.group('request') , 
                      match.group('status') ,
                      match.group('size')
                     )
                   )


logLine = """180.76.15.30 - - [24/Mar/2017:19:37:57 +0000] "GET /shop/page/32/?count=15&orderby=title&add_to_wishlist=4846 HTTP/1.1" 404 10202 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"""
result = parser(logLine)
print(result)