【问题标题】:Parsing corrupt Apache logs using regex使用正则表达式解析损坏的 Apache 日志
【发布时间】:2019-07-02 22:02:21
【问题描述】:

我正在编写一个 Python 3.7.2 程序来解析 Apache 日志以查找所有成功的响应代码。我现在已经编写了正则表达式,它将所有正确的 Apache 日志条目解析为 [origin] [date/time] [HTML method/file/protocol] [response code] 和 [file size] 的单个元组,然后我只是检查查看响应代码是否为 3xx。问题是有几个条目已损坏,有些已损坏到无法读取,因此我已将它们剥离到程序的不同部分。有几个只是缺少方法/协议项上的结束“(引号),导致它每次解析该行时都会引发错误。我想我需要使用 RegEx Or 表达式来表示“ OR 空格,但这似乎将引号分成不同的元组项,而不是寻找说,“GET 613.html HTTP/1.0”或“GET 613.html HTTP/1.0 我是正则表达式的新手,完全被难住了,谁能解释我在做什么错了吗?

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

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

"(.*)?("|\s) - 创建另一个元组项并仍然抛出错误

这是日志条目的 sn-p,包括最后一个缺少它的条目正在关闭“

本地 - - [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 303 728

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(最近一次通话最后一次): 文件“test.py”,第 24 行,在 line = re.match(regex, array[i]).groups() AttributeError:“NoneType”对象没有属性“组”

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

【问题讨论】:

  • 参见regex101.com/r/JQBzBH/1,您可以将表达式更改为([(\w+)]+) - - \[(.*?)\] "(.*)?"? (\d+) (\S+)(有效地使最后一个引号可选)。不过,可能还有更好的方法。
  • 试试logstash,它很容易使用和注入你的Apache或任何类型的日志。您还可以根据需要过滤日志并进行查询。见elastic.co/guide/en/logstash/current/config-examples.html
  • 我认为你必须在 python 中用反斜杠转义 " 字符
  • @jan ([(\w+)]+) - - \[(.*?)\] "(.*)?"? (\d+) (\S+) 正是我修复该特定错误所需要的。我遇到了其他一些不同格式的错误,并且能够使用 | 修复一些错误。并保持分组相同。尽管我开始认为正则表达式对我没有帮助,但有很多损坏/错误的日志与正常的 apache 语法不匹配。在我决定我可能会在这个兔子洞里走得太深之前,我的正则表达式有 4 个组,由条形分隔。这是一个课堂作业,所以我可能只是朝着错误的方向前进。检查 logstash 看看它是否会有所帮助。

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


【解决方案1】:

所以我最初使用 re.match 和 ([(\w+)]+) - - \[(.*?)\] "(.*?)" (\d+) (\d+)Try: / Except: continue 代码来解析所有实际匹配模式的日志。由于 ~750,000 行中有 ~100,000 行不符合正确的 Apache 日志模式,我最终将代码更改为 re.search,改为使用更小的段。

例如:

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 行之外的所有行,其中大部分没有可用信息)更多很重要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    相关资源
    最近更新 更多