JohnyMastricht
@JohnyMastricht
guitarplayer

Как правильно пропарсить access.log с python?

Всем привет. Есть задача сформировать таблицу, содержащую время и коды ответа для запросов. Например:
Time, 200, 30x, 40x, 50x
10/Aug/2015:12:12:01, 7, 2, 0, 1

То есть, для указанного времени наблюдалось 7 запросов с ответом "200", 2 - вида "302" или "304", и так далее.

Строка access.log имеет следующий шаблон:
8.8.8.8 - - [10/Aug/2015:12:12:01 +0000] "GET /robots.txt HTTP/1.1" 200 708 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +www.google.com/bot.html)"

На python сформировал код вида:
#!/usr/bin/python
import re
for string in open("access.log","r"):
 ws = string.split()
 i=0
 r=0
 n=0
 x=0
 matchi = re.findall(r'^2..',ws[8])
 if matchi:
  i=i+1
 matchr = re.findall(r'^3..',ws[8])
 if matchr:
  r=r+1
 matchn = re.findall(r'^4..',ws[8])
 if matchn:
  n=n+1
 matchx = re.findall(r'^5..',ws[8])
 if matchx:
  x=x+1
 print ws[3].replace('[',''), i, r, n, x

На выходе получаю:
10/Aug/2015:12:12:01 1 0 0 0
10/Aug/2015:12:12:01 0 1 0 0
10/Aug/2015:12:12:01 0 1 0 0
10/Aug/2015:12:12:01 0 1 0 0

Вопрос: а как теперь сложить значения и вывести уникальное время(какие средства python или алгоритм использовать), то есть, чтоб для данного примера вывода получилось:
10/Aug/2015:12:12:01 1 3 0 0
  • Вопрос задан
  • 774 просмотра
Решения вопроса 1
adugin
@adugin Куратор тега Python
from collections import Counter, defaultdict
from itertools import imap
import re

codes = ['200', '3xx', '4xx', '5xx']
regex = re.compile('^.+?\[(?P<date>.+?) .+?\].+?(?P<code>\d+) \d+ ".+?" ".+?"$')
stats = defaultdict(Counter)

with open('access.log', 'r') as f:
    for date, code in (match.groups() for match in imap(regex.match, f) if match):
        stats[date].update([code if code == '200' else '{}xx'.format(code[0])])

for date, items in sorted(stats.iteritems()):
    print date, ' '.join(str(items[code]) for code in codes)

# ---------- И ещё вариант ----------

from collections import Counter, defaultdict
from itertools import imap
from operator import methodcaller as mc
import re

codes = ['200', '3xx', '4xx', '5xx']
regex = re.compile('^.+?\[(?P<date>.+?) .+?\].+?(?P<code>\d+) \d+ ".+?" ".+?"$')
stats = defaultdict(Counter)

def fmt(code):
    return code if code == '200' else '%sxx' % code[0],

with open('access.log', 'r') as f:
    reduce(
        lambda _, (date, code): stats[date].update(fmt(code)),
        imap(mc('groups'), imap(regex.match, f)), None
    )

for date, items in sorted(stats.iteritems()):
    print date, ' '.join(imap(str, imap(items.__getitem__, codes)))

</code>
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
sim3x
@sim3x
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы