使用python和re.findall,I';我试图计算apache日志中有效的域命中数

使用python和re.findall,I';我试图计算apache日志中有效的域命中数,python,regex,apache,findall,logfile,Python,Regex,Apache,Findall,Logfile,这是我的日志文件中“有效”行的一个示例: 194.81.31.125---[129/Dec/2013:22:03:09-0500]“获取http://www.firemaiden.hu/cgi-bin/top/topsites.cgi?an12 HTTP/1.0“200 558”http://Afrique“Mozilla/4.0(兼容;MSIE 5.5;Windows 98)” 我得到了这个re.findall表达式:(GET | POST)\s(http://https/)[a-zA-Z]+

这是我的日志文件中“有效”行的一个示例:
194.81.31.125---[129/Dec/2013:22:03:09-0500]“获取http://www.firemaiden.hu/cgi-bin/top/topsites.cgi?an12 HTTP/1.0“200 558”http://Afrique“Mozilla/4.0(兼容;MSIE 5.5;Windows 98)”

我得到了这个re.findall表达式:
(GET | POST)\s(http://https/)[a-zA-Z]+.+?“\s200
此表达式包含有效行的所有规则,但不提取域

我想对每个日期的顶级域(本例中为“hu”)进行计数,并将每个域的计数转储到一个有组织的日志文件中。我还想将无效行提取到另一个日志文件中

理想情况下,输出为:

2013年12月12日[tab]as:1[tab]ab:2[tab]hu:4


2013年12月13日[tab]as:4[tab]br:7[tab]cd:8

当然,它不会提取域;您没有通过将域括在括号中将其放入捕获组

因此,首先要做的是添加括号:

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-\.]
,对吗

但许多服务器也会接受下划线并将其视为连字符,有些服务器会将()名称解码为Unicode以进行日志记录,因此即使这样也可能不对

综上所述,我认为,与其使用您不知道如何编写并且可能不理解的regexp,不如使用更简单的regexp来获取URL(您已经知道如何做),然后使用专用的URL解析器来破解它:

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


现在
p.scheme
是您的
'http'
'https'
p.netloc
'www.firemaiden.hu'
(您可以很容易地称之为
.split('.')[-1]
)等。

感谢您提供的信息……我很好奇如何解决域服务器仅位于一个“.”之后的情况。例如:
http://firemaiden.com
@kegewe:你说的“如何解决这种情况”是什么意思"?你试过我的任何一个例子吗?这两个例子都为你提供了该URL的
com
。这不是你想要的吗?对不起,我没有使用urllib,而是尝试了你建议的对正则表达式的第一次修改,我能够将域作为元组输出的第三个元素。现在我只需要组织输出。@kegewe:哪一个?如答案中所述,前两个根本不起作用。第三个,为
www.firemaiden.hu
工作的,也为
firemaiden.com
工作。那么,你有什么问题吗?似乎第三个也返回了一些非顶级域的值。例如,它返回了一个类似“sou”的词地址:www.southern-charms.com
p = urllib.parse.urlparse(match[1])