[英]Python: Parsing a log file without convenient delimiters or fixed-width
我正在努力解决一个愚蠢的简单问题。 我正在尝试解析如下所示的 .log 文件:
#Software: Microsoft Internet Information Services 10.0
#Version: 1.0
#Date: 2020-03-31 00:00:40
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
2020-03-31 00:00:40 172.33.22.75 GET /alcatel_tracfone_phone.html - 443 - 12.123.23.456 okhttp/3.12.1 - 200 0 0 32
...
2020-03-31 00:01:03 172.33.22.75 GET /jose_laptop_windows.html - 443 - 170.173.81.52 curl/7.55.1 - 404 0 2 125
列如下:
date
time
s-ip
cs-method
cs-uri-stem
cs-uri-query
s-port
cs-username
c-ip
cs(User-Agent)
cs(Referer)
sc-status
sc-substatus
sc-win32-status
time-taken
我想要一个 Pandas 表,其中包含日志文件中每个列的列。 请注意,没有可用于整洁解析的方便分隔符,也没有固定宽度。 这在 Excel 中很简单,在 Python 中可能很简单,但我已经挣扎了几个小时没有运气。 有人可以提供完整的代码解决方案供我学习吗?
更新:
哇,我傻了。 非常感谢大家。 我不熟悉read_csv()
function 并一直在谷歌上搜索每个步骤:1.如何跳过日志文件的行(跳过前 4 行),2.我看到其他使用“字段”参数的示例,但是没有意识到它可能是空格分隔的; 3. 我不知道.log
文件可以被视为与.csv
相同,或者更确切地说,可以用作名为read_csv()
的 function 的输入。
这里的分隔符不是空格吗?
pd.read_csv(file, delimiter=' ')
或者,要完整:
cols = 'date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken'.split(' ')
pd.read_csv('overflow.csv',
delimiter=' ',
comment='#',
names=cols)
给出(因大小而切片):
print(df.iloc[:,-5:])
cs(Referer) sc-status sc-substatus sc-win32-status time-taken
0 - 200 0 0 32
1 - 404 0 2 125
为什么不使用空格作为分隔符:
fields = 'date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken'.split(' ')
df = pd.read_csv('/path/to/file.txt', sep=' ', header=None, skiprows=4, names=fields)
如果您的文件或数据没有分隔符。 您必须通过正则表达式读取文件并将数据提取到列表中。 最后将列表中的 dict 转换为 dataframe
因为我没有你的完整数据集。 下面以一块为例:
# Dataset Example
2020-03-31 00:00:40 172.31.11.70 GET
2020-03-31 00:01:03 172.31.11.70 GET
import re
import pandas as pd
data_list = []
column_name_list = ["Date", "Time", "IP", "Method"]
regex = r"^(\d\d\d\d-\d\d-\d\d) (\d\d:\d\d:\d\d) \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b (GET|POST)$"
test_str = (
"2020-03-31 00:00:40 172.31.11.70 GET\n"
"2020-03-31 00:01:03 172.31.11.70 POST"
)
matches = re.finditer(regex, test_str, re.MULTILINE)
for matchNum, match in enumerate(matches, start=1):
row_dict = {}
for groupNum in range(0, len(match.groups())):
groupNum = groupNum + 1
row_dict.update({column_name_list[groupNum]: match.group(groupNum)})
print(row_dict)
print(
"Group {groupNum} found at {start}-{end}: {group}".format(
groupNum=groupNum,
start=match.start(groupNum),
end=match.end(groupNum),
group=match.group(groupNum),
)
)
data_list.append(row_dict)
## Output
## Time IP Method
## 0 2020-03-31 00:00:40 GET
## 1 2020-03-31 00:01:03 POST
您需要找出数据集的正则表达式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.