我正在使用 Python 3 CSV 阅读器将一些网络日志文件读入命名元组中。 我无法控制日志文件结构,并且有多种类型。
分隔符是一个空格( ),问题是一些日志文件格式在时间戳中放置了一个空格,如下面的Logfile 2。 CSV 阅读器然后将日期/时间戳记为两个字段。
日志文件 1
73 58 2993 [22/Jul/2016:06:51:06.299] 2[2] "GET /example HTTP/1.1"
13 58 224 [22/Jul/2016:06:51:06.399] 2[2] "GET /example HTTP/1.1"
日志文件 2
13 58 224 [22/Jul/2016:06:51:06 +0000] 2[2] "GET /test HTTP/1.1"
153 38 224 [22/Jul/2016:06:51:07 +0000] 2[2] "GET /test HTTP/1.1"
日志文件通常在方引号内包含时间戳,但我找不到将它们作为“引号”处理的方法。最重要的是,方括号也不总是在日志中用作引号(请参阅日志后面的 [2])。
我已经通读了 Python 3 CSV Reader documentation ,包括方言,但似乎没有任何东西可以处理方括号。
如何自动处理这种情况?
请您参考如下方法:
这样就可以了,您需要使用正则表达式代替 sep。
例如,这会将 NGinx 日志文件解析为 pandas.Dataframe:
import pandas as pd
df = pd.read_csv(log_file,
sep=r'\s(?=(?:[^"]*"[^"]*")*[^"]*$)(?![^\[]*\])',
engine='python',
usecols=[0, 3, 4, 5, 6, 7, 8],
names=['ip', 'time', 'request', 'status', 'size', 'referer', 'user_agent'],
na_values='-',
header=None
)
编辑:
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 条信息的元组
('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')
