使用正则表达式解析损坏的Apache日志

时间:2019-02-08 16:03:21

标签: regex python-3.x parsing html-parsing

我正在编写一个Python 3.7.2程序来解析Apache日志,以查找所有成功的响应代码。我现在已经编写了正则表达式,它将所有正确的Apache日志条目解析为[来源] [日期/时间] [HTML方法/文件/协议] [响应代码]和[文件大小]的单个元组,然后我只检查查看响应代码是否为3xx。问题是有几个条目已损坏,有些条目已损坏到无法读取,因此我将它们剥离到程序的其他部分。一些方法只是缺少方法/协议项上的“”(引号),导致每次我解析该行时都会引发错误。我在想我需要使用RegEx Or表达式作为“ OR空格,但这似乎将报价单分成一个不同的元组项目,而不是查找“ GET 613.html HTTP / 1.0”或“ GET 613.html HTTP / 1.0”。我是regex的新手,并且已彻底陷入困境,任何人都可以解释我在做什么错误吗?

我应该注意,日志中已经清除了一些信息,而不是原始IP,它仅显示“本地”或“远程”,并且操作系统/浏览器信息已完全删除。

这是与有效条目有效的相关元组项目的正则表达式:“(。*)?”我也尝试过:

“(。*)?(” | \ s)-创建另一个元组项,但仍会引发错误

这是日志条目的摘要,其中包括最后一个缺少的条目“

本地--[27 / Oct / 1994:18:47:03 -0600]“ GET index.html HTTP / 1.0” 200 3185
本地--[27 / Oct / 1994:18:48:53 -0600]“ GET index.html HTTP / 1.0” 404-
本地--[27 / Oct / 1994:18:49:55 -0600]“ GET index.html HTTP / 1.0” 303 3185
本地--[27 / Oct / 1994:18:50:25 -0600]“ GET 612.html HTTP / 1.0” 404-
本地--[27 / Oct / 1994:18:50:41 -0600]“ GET index.html HTTP / 1.0” 200 388
本地--[27 / Oct / 1994:18:50:52 -0600]“ GET 613.html HTTP / 1.0 303728

regex = '([(\w+)]+) - - \[(.*?)\] "(.*)?" (\d+) (\S+)'
import re

with open("validlogs.txt") as validlogs:                
    i = 0
    array = []
    successcodes = 0
    for line in validlogs:                               
        array.append(line)
        loglength = len(array)                               

    while (i < loglength):                               
        line = re.match(regex, array[i]).groups()
        if(line[3].startswith("3")):
            successcodes+=1
        i+=1
    print("Number of successcodes: ", successcodes)

解析上面的日志响应应该给出成功代码数:2 相反,我得到了:Traceback(最近一次通话):   在第24行中输入文件“ test.py”     行= re.match(regex,array [i])。groups() AttributeError:'NoneType'对象没有属性'groups'

因为(我相信)正则表达式正在明确寻找“”,并且无法处理缺少它的行条目。

1 个答案:

答案 0 :(得分:0)

因此,我最初使用带有([(\w+)]+) - - \[(.*?)\] "(.*?)" (\d+) (\d+) / Try:代码的Except: continue的re.match来解析实际上与该模式匹配的所有日志。由于〜750,000行中的〜100,000不符合正确的Apache日志模式,因此我将代码更改为使用较小的段重新进行搜索。

例如:

with open("./http_access_log.txt") as logs:             
    for line in logs:
        if re.search('\s*(30\d)\s\S+', line):         #Checking for 30x redirect codes
            redirectCounter += 1  

我读到re.match比re.search快,但是我觉得能够准确地捕获最可能的日志条目(这处理了除2000行之外的所有行,其中大多数没有可用信息)更多。重要。