Используя 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]
и т. д.)