"Достать" 10 самых частых запросов по ip из access.log

Выполняю учебное задание, в котором надо достать из лога Apache-сервера 10 самых частых запросов по ip.

Пример записи из access.log:

109.169.248.247 - - [12/Dec/2015:18:25:11 +0100] "POST /administrator/index.php HTTP/1.1" 200 4494 "http://almhuette-raith.at/administrator/" "Mozilla/5.0 (Windows NT 6.0; rv:34.0) Gecko/20100101 Firefox/34.0" 4374

Написал такой код:

import argparse
import json
import re
from collections import defaultdict, Counter


parser = argparse.ArgumentParser(description="Парсер для access.log")
parser.add_argument('-f', dest="logfile", action='store', default='access.log')
args = parser.parse_args()

r_ip = (r"^(?P<ip>.*?)\s")  

def top10_ips():
    d_ips = defaultdict(list)
    with open(args.logfile) as f:
        for line in f.readlines():
            try:
                ips = re.search(r_ip, line).group()
            except AttributeError:
                pass
            d_ips[ips] += 1
            return Counter(d_ips).most_common(10)
print(json.dumps(top10_ips(), indent=4))

По выполнению вот такая ошибка:

Traceback (most recent call last):
  File "E:/Gitlabo/repo_1/Autotesto_Loggs-Nick/access_logparser.py", line 26, in <module>
    print(json.dumps(top10_ips(), indent=4))
  File "E:/Gitlabo/repo_1/Autotesto_Loggs-Nick/access_logparser.py", line 24, in top10_ips
    d_ips[ips] += 1
TypeError: 'int' object is not iterable

Я понимаю, что интеджер это число, но вот как исправить не пойму. Заранее спасибо


Ответы (2 шт):

Автор решения: Константин Рыбаков

d_ips = defaultdict(list) тут вы делаете словарь у которого дефолтное значение лист.

d_ips[ips] += 1 # d_ips[ips] не найдено и вместо key error вам отдают пустой лист, который вы пытаетесь сложить с числом, потому ругается.

Сначала сделайте проверку:

if ips in d_ips:
    d_ips[ips] += 1
else: 
    d_ips[ips] = 1
→ Ссылка
Автор решения: CrazyElf

Вы определитесь - либо за вас будет считать Counter и тогда код должен быть примерно таким:

d_ips = Counter()
...
d_ips.update([ips])
...
return d_ips.most_common(10)

Либо вы считаете сами, тогда код примерно такой:

d_ips = defaultdict(int)
...
d_ips[ips] += 1
...
return dict(d_ips)

Но в этом случае вам как-то нужно будет ещё отобрать самостоятельно 10 наиболее частых записей.

А у вас какая-то помесь получилась разных вариантов, вам нужно разобраться, что вы вообще делаете.

→ Ссылка