使用正则表达式解析日志时不断出现“NoneType”错误
Keep getting `NoneType` errors when parsing logs with regex
下面是两个日志的示例。我正在尝试获取 ip、date_time、方法、这部分 (/071300/242153 HTTP/1.1"
)、响应代码(只是 404
/200
部分),其余部分在一组:
66.249.69.97 - - [24/Sep/2014:22:25:44 +0000] "GET /071300/242153 HTTP/1.1" 404 514 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
和
71.19.157.174 - - [24/Sep/2014:22:26:12 +0000] "GET /error HTTP/1.1" 404 505 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
我的函数如下所示:
def parse_logs(logs):
log_list = []
for log in logs:
p = re.compile(r'''(?P<ip_addr>\d+(\.\d+){3}) - - \[(?P<date_time>.+?)\] (?P<http_method>\".+?\") (?P<return_code>\d+) \d+ "-" (?P<client>\".+?\")''')
m = p.search(log)
log_list.append([m.group('ip_addr'), m.group('date_time'), m.group('http_method'), m.group('return_code'), m.group('client')])
rdd_prepped = parse_logs(rdd.take(5))
当我将这些日志的列表传递给函数并 运行 它时,我不断收到错误消息:
AttributeError: 'NoneType' object has no attribute 'collect'
.
当我在 m = p.search(log)
下放置 print(m.group('ip'))
行时,出现错误:
AttributeError: 'NoneType' object has no attribute 'group'
为什么我总是收到 NoneTypes?我正在使用 Python2.7 btw.
首次发布时,正则表达式如下所示:
p = re.compile(r'''(?P<ip>\d+(\.\d+){3}) - - \[(?P<date_time>.+?)\] (?P<method>\".+?\") \
(?P<response_code>\d+) \d+ "-" (?P<client>\".+?\")''')
注意第一行末尾的续行符(“\”)。但该模式也包含在三重引号中。因此该模式包括文本 '\n '
(斜线 + 换行符 + 缩进)。结果,模式不匹配。
在一行中重写模式,它应该可以工作:
p = re.compile(r'''(?P<ip>\d+(\.\d+){3}) - - \[(?P<date_time>.+?)\] (?P<method>\".+?\") (?P<response_code>\d+) \d+ "-" (?P<client>\".+?\")''')
对于复杂的正则表达式,我喜欢使用verbose模式:
regex = re.compile("""
(?P<ip>\d+(?:\.\d+){3}) # four, dot-separated sets of digits
.*? # skip ahead
\[(?P<date_time>.*?)\] # date time is everything between '[ ]'
.*? # skip
"(?P<method>.*?)" # method is everything between quotes
.*? # skip
(?P<response_code>\d+) # multiple digits
.*? # skip
"-" # don't care
.*? #
"(?P<client>.*?)" # client is everything between quotes
""", re.VERBOSE)
还有一些事情:
如果您希望正则表达式匹配(几乎)日志中的每一行,那么您应该 print/log 任何不匹配的行。这有助于捕获正则表达式中的错误,或者当有人在不通知您的情况下更改日志格式时。
将 re.compile 步骤移出循环。
MatchObject.group()
可以采用多个参数和 returns 列出的组的元组。
def parse_logs(logs):
log_list = []
p = re.compile(...whichever regex style you like...)
for log in logs:
m = p.search(log)
if m:
log_list.append(m.group('ip_addr', 'date_time', 'http_method,
'return_code', 'client'))
else:
print(log)
rdd_prepped = parse_logs(rdd.take(5))
下面是两个日志的示例。我正在尝试获取 ip、date_time、方法、这部分 (/071300/242153 HTTP/1.1"
)、响应代码(只是 404
/200
部分),其余部分在一组:
66.249.69.97 - - [24/Sep/2014:22:25:44 +0000] "GET /071300/242153 HTTP/1.1" 404 514 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
和
71.19.157.174 - - [24/Sep/2014:22:26:12 +0000] "GET /error HTTP/1.1" 404 505 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36"
我的函数如下所示:
def parse_logs(logs):
log_list = []
for log in logs:
p = re.compile(r'''(?P<ip_addr>\d+(\.\d+){3}) - - \[(?P<date_time>.+?)\] (?P<http_method>\".+?\") (?P<return_code>\d+) \d+ "-" (?P<client>\".+?\")''')
m = p.search(log)
log_list.append([m.group('ip_addr'), m.group('date_time'), m.group('http_method'), m.group('return_code'), m.group('client')])
rdd_prepped = parse_logs(rdd.take(5))
当我将这些日志的列表传递给函数并 运行 它时,我不断收到错误消息:
AttributeError: 'NoneType' object has no attribute 'collect'
.
当我在 m = p.search(log)
下放置 print(m.group('ip'))
行时,出现错误:
AttributeError: 'NoneType' object has no attribute 'group'
为什么我总是收到 NoneTypes?我正在使用 Python2.7 btw.
首次发布时,正则表达式如下所示:
p = re.compile(r'''(?P<ip>\d+(\.\d+){3}) - - \[(?P<date_time>.+?)\] (?P<method>\".+?\") \
(?P<response_code>\d+) \d+ "-" (?P<client>\".+?\")''')
注意第一行末尾的续行符(“\”)。但该模式也包含在三重引号中。因此该模式包括文本 '\n '
(斜线 + 换行符 + 缩进)。结果,模式不匹配。
在一行中重写模式,它应该可以工作:
p = re.compile(r'''(?P<ip>\d+(\.\d+){3}) - - \[(?P<date_time>.+?)\] (?P<method>\".+?\") (?P<response_code>\d+) \d+ "-" (?P<client>\".+?\")''')
对于复杂的正则表达式,我喜欢使用verbose模式:
regex = re.compile("""
(?P<ip>\d+(?:\.\d+){3}) # four, dot-separated sets of digits
.*? # skip ahead
\[(?P<date_time>.*?)\] # date time is everything between '[ ]'
.*? # skip
"(?P<method>.*?)" # method is everything between quotes
.*? # skip
(?P<response_code>\d+) # multiple digits
.*? # skip
"-" # don't care
.*? #
"(?P<client>.*?)" # client is everything between quotes
""", re.VERBOSE)
还有一些事情:
如果您希望正则表达式匹配(几乎)日志中的每一行,那么您应该 print/log 任何不匹配的行。这有助于捕获正则表达式中的错误,或者当有人在不通知您的情况下更改日志格式时。
将 re.compile 步骤移出循环。
MatchObject.group()
可以采用多个参数和 returns 列出的组的元组。
def parse_logs(logs):
log_list = []
p = re.compile(...whichever regex style you like...)
for log in logs:
m = p.search(log)
if m:
log_list.append(m.group('ip_addr', 'date_time', 'http_method,
'return_code', 'client'))
else:
print(log)
rdd_prepped = parse_logs(rdd.take(5))