2013-06-26 124 views
2

好日子全部,Python和正則表達式

我之前發佈了類似的東西,所以如果您再次遇到這個問題,我很抱歉。這一次我會更具體,給你直接的例子,並描繪出我想要的。基本上,我需要讓原始數據看起來更漂亮:

str = '2011-06-1618:53:41222.222.2.22-somedomain.hi.comfw12192.10.215.11GET/965874/index.xls22233665588-0Mozilla/4.0 (compatible; MSI 5.5; Windows NT 5.1)'--55656-0.55-5874/659874540--' 



more strings: 
'2011-06-2150:36:1292.249.2.105-somedomain.hi.comfw12192.10.215.11GET/965874/ten.xls22233665588-0Mozilla/4.0 (compatible; MSI 6.0; Windows NT 5.1)'--55656-0.55-5874/659874540--' 
'2011-01-1650:23:45123.215.2.215-somedomain.hi.comfw12192.10.215.11GET/123458/five.xls22233665588-0Mozilla/4.0 (compatible; MSI 7.0; Windows NT 5.1)'--55656-0.55-5874/659874540--' 
'2011-02-1618:16:54129.25.2.119-thisdomain.hi.comfw12192.10.215.11GET/984745/two.xls22233665588-0Mozilla/4.0 (compatible; MSI 7.0; Windows NT 5.1)'--55656-0.55-5874/659874540--' 
'2011-08-0525:22:16164.32.2.111-yourdomain.hi.comfw12192.10.215.11GET/85472/one.xls22233665588-0Mozilla/4.0 (compatible; MSI 8.0; Windows NT 5.1)'--55656-0.55-5874/659874540--' 

在調試器:

import re 
str = '2011-06-1618:53:41222.222.2.22-somedomain.hi.comfw12192.10.215.11GET/965874/index.xls22233665588-0Mozilla/4.0 (compatible; MSI 5.5; Windows NT 5.1)'--55656-0.55-5874/659874540--' 
domain = re.compile('^.*?(?=([fw].+?))') 
domain.search(str).group() 
'2011-06-1618:53:41222.222.2.22-somedomain.hi.com' 
domain = domain.search(str).group() 

所以對於獲取域,我需要的破折號前擺脫一切( - ),右在域名之前。我可以用這個RE([0-9] {3,5})。([0-9] {1,3}。){2} [0-9] {1,3} [ - ]但我不知道該怎麼說,找到那個價值並且在它之後回覆一切,但是在fw12之前。

在一天結束的時候,我想這些字符串看起來像這樣,用逗號(,)作爲分隔符:

2011-08-05,25:22:16,164.32.2.111,YOURDOMAIN .hi.com,GET/85472/one.xls,Mozilla/4.0(兼容; MSI 8.0; Windows NT 5.1)

+0

爲了解析這個問題,無論您使用哪種技術,您都需要有一些方法來區分域名後面的部分和後面的任何部分。你能用英語表達怎麼做?下列文字是否總是「fw12」,並且域名是否沒有該字符串? –

+0

網絡日誌不帶字段之間的分隔符?奇怪的配置:s – MatToufoutu

+0

是在特定範圍內的所有IP地址?如果不是這樣,則可能很難構建能夠意識到「fwXX」部分的結尾以及IP地址的開頭的正則表達式。 – MatToufoutu

回答

0

要分隔每個字段,我建議你使用這種模式(然後你加入與分隔符你想要的):

(\d{4}-\d{2}-\d{2})(\d{2}:\d{2}:\d{2})(\d+(?:\.\d+){3})-([a-z.]+)fw\d+(?:\.\d+){3}(GET\/\d+\/[a-z.]+)[-\d]+([^'-]+) 
2

首選,但是,也許 - 不可行的方法

這看起來像(如MatToufoutu指出的)Apache日誌文件。如果確實如此,那麼你可以使用apachelog或類似的東西來處理它。您需要將Apache的httpd.conf/apache2.conf文件字符串用作格式化程序。由於我沒有你,我只是用apachelog中提供的一個的文檔:

import apachelog 

format = r'%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" ' 
log_line = """212.74.15.68 - - [23/Jan/2004:11:36:20 +0000] "GET /images/previous.png HTTP/1.1" 200 2607 "http://peterhi.dyndns.org/bandwidth/index.html" "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2) Gecko/20021202" """ 

p = apachelog.parser(format) 
data = p.parse(log_line) 

然後,您可以通過訪問data訪問日誌文件的各個部分的屬性

print "%s, %s, %s, %s, %s" % (data['%t'], data['%h'], data['%{Referer}i'], data['%r'], data['%{User-Agent}i']) 

以獲得輸出

[23 /月/ 2004:11:36:20 0000],212.74.15.68,http://peterhi.dyndns.org/bandwidth/index.html,GET /images/previous.png HTTP/1.1

使用正則表達式

或者,你可以把你的初步做法和使用正則表達式來解析線。以下應該工作。他們分成命名組,以便更容易A)閱讀B)編輯C)理解:

import re 


your_string = "2011-06-1618:53:41222.222.2.22-somedomain.hi.comfw12192.10.215.11GET/965874/index.xls22233665588-0Mozilla/4.0 (compatible; MSI 5.5; Windows NT 5.1)'--55656-0.55-5874/659874540--" 

pattern = re.compile(r'(?P<date>\d{4}(:?-\d{2}){2})(?P<time>(:?\d{2}:?){3})(?P<ip_address1>(:?\d{1,3}\.?){4})-(?P<domain>[\w\.]+)fw12(?P<ip_address2>(:?\d{1,3}\.?){4})(?P<get>(:?GET/(:?\d+/)).*?)\d+-0(?P<user_agent>.*?)\'--.*$') 
result = pattern.match(your_string) 

然後,您可以訪問結果與result.group('groupname'),如:

print "%s %s, %s, %s, %s, %s" % (result.group('date'), result.group('time'), result.group('ip_address1'), result.group('domain'), result.group('get'), result.group('user_agent')) 

哪將返回:

2011-06-16 18:53:41,222.222.2.22,somedomain.hi.com,GET/965874/index.xls,Mozilla/4.0(兼容; MSI 5.5; Windows NT 5 。1)

由於用正則表達式這種方法交易,我總是喜歡加我的小免責聲明:

你的數據進行解析。它落在你和你對需要多少寬容,衛生和驗證的判斷上。您可能需要修改上述內容以更好地滿足您的要求,並且可以使用未包含在樣本中的現實世界數據正確工作。確保你瞭解正則表達式正在做什麼,以便你知道這個代碼是如何工作的。