2011-01-05 37 views
1

我試圖獲得使用從HTML文件的正則表達式的數據中提取源代碼的HTML文件,通過執行以下代碼:使用python3.1 urllib.request裏

​​

返回一個錯誤:

File "extract.py", line 33, in extract_words 
match = re.findall("<tr>\s*<td>([\w\s.;'(),-/]+)</td>\s+<td>([\w\s.,;'()-/]+)</td>\s*</tr>", text) 
File "/usr/lib/python3.1/re.py", line 192, in findall 
return _compile(pattern, flags).findall(string) 
TypeError: can't use a string pattern on a bytes-like object 

當在IDLE進一步試驗,我注意到uf.read()確實返回第一次調用它的HTML源代碼。但之後,它返回一個-b「'。有什麼辦法可以解決這個問題嗎?

回答

2

uf.read()只會讀取一次內容。然後你必須關閉它並重新打開它再次閱讀。對於任何類型的流都是如此。但這不是問題。

問題是,從任何類型的二進制源文件(如文件或網頁)中讀取數據將返回bytes類型的數據,除非指定了編碼。但是,您的正則表達式未指定爲bytes類型,它指定爲unicode str

re模塊將非常合理地拒絕在字節數據上使用unicode模式,反之亦然。

解決的辦法是讓正則表達式模式成爲一個字節字符串,通過將b放在它的前面來完成。因此:

match = re.findall(b"<tr>\s*<td>([\w\s.;'(),-/]+)</td>\s+<td>([\w\s.,;'()-/]+)</td>\s*</tr>", text) 

應該工作。另一種選擇是將文本解碼,所以它也是一個unicode str

encoding = uf.headers.getparam('charset') 
text = text.decode(encoding) 
match = re.findall("<tr>\s*<td>([\w\s.;'(),-/]+)</td>\s+<td>([\w\s.,;'()-/]+)</td>\s*</tr>", text) 

(此外,爲了提取HTML數據,我會說,lxml是一個更好的選擇)。

相關問題