Используя python и re.findall, я пытаюсь подсчитать количество действительных посещений домена в журнале Apache

Это пример 'допустимой' строки в моем файле журнала:194.81.31.125 - - [129/Dec/2013:22:03:09 -0500] "GET http://www.firemaiden.hu/cgi-bin/top/topsites.cgi?an12 HTTP/1.0" 200 558 "http://Afrique" "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)"

У меня есть это выражение re.findall: (GET|POST)\s(http://|https//)[a-zA-Z]+.+?"\s200Это выражение содержит все правила для допустимой строки, но не извлекает домен.

Я хочу подсчитать домены верхнего уровня, в данном случае "hu", для каждой даты и записать количество для каждого домена в организованный файл журнала. Я также хочу извлечь недействительные строки в другой файл журнала

выход в идеале это:

12/Dec/2013[tab]as:1[tab]ab:2[tab]hu:4

13/Dec/2013[tab]as:4[tab]br:7[tab]cd:8

1 ответ

Решение

Конечно, он не извлекает домен; вы не поместили это в группу захвата, заключив ее в скобки.

Итак, первое, что нужно сделать, это добавить скобки:

r'(GET|POST)\s(http://|https//)([a-zA-Z]+.+?)"\s200'

Но это все еще не правильно, поскольку это захватит весь www.firemaiden.hu/cgi-bin/top/topsites.cgi?an12 HTTP/1.0не только www.firemaiden.hu, Это потому, что у вас есть только одна группа букв, за которыми следует что-либо, вплоть до цитаты. Вам нужны только буквы и точки (что на самом деле не правильно для DNS, но давайте пока проигнорируем это). Как это:

r'(GET|POST)\s(http://|https//)([a-zA-Z\.]+).+?"\s200'

И теперь вы получаете www.firemaiden.hu,

Но вы хотели только .hu, право? Итак, что вам действительно нужно как можно больше букв и точек, вплоть до группы букв только после точки:

r'(GET|POST)\s(http://|https//)[a-zA-Z\.]+\.([a-zA-Z]+).+?"\s200'

Тем не менее, вы захотите прочитать правила для DNS-имен, которые теоретически доступны каждому корневому серверу. Но все под стандартными мировыми корнями следует правилу LDH: буквы, цифры, дефисы. Итак, вы хотите [a-zA-Z0-9-\.], право?

Но многие серверы также принимают подчеркивания и рассматривают их как дефисы, а некоторые серверы декодируют имена IDNA ( punycode) в Unicode для регистрации, так что даже это может быть неправильно.

Несмотря на это, я думаю, что вместо того, чтобы использовать регулярное выражение, которое вы не знали, как писать, и, возможно, не понимаете, вы идете с более простым регулярным выражением, чтобы получить только URL (который вы уже знаете, как это сделать), а затем используйте выделенный парсер URL, чтобы взломать его:

r'(GET|POST)\s(\S+)\s.*?200'

Затем:

p = urllib.parse.urlparse(match[1])

Сейчас p.scheme твой 'http' или же 'https', p.netloc является 'www.firemaiden.hu' (который вы можете легко назвать .split('.')[-1] и т. д.)

Другие вопросы по тегам