繁体   English   中英

Python:解析没有方便的分隔符或固定宽度的日志文件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM