2012-05-31 77 views
2

我對Python正則表達式有個疑問。我沒有太多有關Python正則表達式的信息。我正在處理HTTP請求消息並用正則表達式解析它們。如您所知,HTTP GET消息採用此格式。HTTP請求標頭的Python正則表達式

GET/HTTP/1.0 
User-Agent: Wget/1.12 (linux-gnu) 
Accept: */* 
Host: 10.2.0.12 
Connection: Keep-Alive 

我想解析消息的URI,方法,用戶代理和主機區域。我對這項工作正則表達式是:

r'^({0})\s+(\S+)\s+[^\n]*$\n.*^User-Agent:\s*(\S+)[^\n]*$\n.*^Host:\s*(\S+)[^\n]*$\n'.format('|'.join(methods)), re.MULTILINE|re.DOTALL) 

但是,該消息出現了像

GET/HTTP/1.0 
Host: 10.2.0.12 
User-Agent: Wget/1.12 (linux-gnu) 
Accept: */* 
Connection: Keep-Alive 

時我無法追上他們,因爲主機的地方或者,用戶代理改變。所以我需要一個通用的正則表達式來捕獲所有這些,即使主機,方法,uri的位置在消息中發生了變化。

+4

[這會幫助你(http://stackoverflow.com/questions/4685217/parse-raw-http-headers) – tuxuday

+0

@tuxuday +1搜索刻着網絡是一個最強大的技能開發人員的工具箱。 –

+0

我喜歡@tuxuday所說的方法。像這樣m = re.findall(r「(?P 。*?):(?P 。*?)\ r \ n」,req)。但是在這個方法中我無法解析「GET」和http版本。在開始時添加它們會更好嗎? – barp

回答

2

解析整個頭部到字典中,像這樣?

headers = """GET/HTTP/1.0 
Host: 10.2.0.12 
User-Agent: Wget/1.12 (linux-gnu) 
Accept: */* 
Connection: Keep-Alive""" 


headers = headers.splitlines() 
firstLine = headers.pop(0) 
(verb, url, version) = firstLine.split() 
d = {'verb' : verb, 'url' : url, 'version' : version} 
for h in headers: 
    h = h.split(': ') 
    if len(h) < 2: 
     continue 
    field=h[0] 
    value= h[1] 
    d[field] = value 

print d 

print d['User-Agent'] 
print d['url'] 
+0

請記住在s1.splitlines()中刪除你的值並忽略不包含':' - 'd = dict([l.split(':')]'中的i [i.strip()如果「:」in l])' –

+0

而+1 - 喜歡你的方法。正如我寫的,可讀性計數。 –

+0

我還需要解析「GET方法」。無':' – barp

5

可讀性計數(The Zen of Python)

使用findall()您要找到每個子表達式。這樣你的正則表達式就會變得簡短易讀,並且獨立於子表達式的位置。

定義一個簡單的,可讀的正則表達式:

>>> user=re.compile("User-Agent: (.*?)\n") 

測試這兩種不同的HTTP標頭:

>>> s1='''GET/HTTP/1.0 
    Host: 10.2.0.12 
    User-Agent: Wget/1.12 (linux-gnu) 
    Accept: */* 
    Connection: Keep-Alive''' 
>>> s2='''GET/HTTP/1.0 
    User-Agent: Wget/1.12 (linux-gnu) 
    Accept: */* 
    Host: 10.2.0.12 
    Connection: Keep-Alive''' 
>>> user.findall(s1) 
['Wget/1.12 (linux-gnu)'] 
>>> user.findall(s2) 
['Wget/1.12 (linux-gnu)']