2011-01-05 5 views
1

mit Ich versuche, Daten mithilfe von regulären Ausdrücken aus einer HTML-Datei zu erhalten, indem Sie den folgenden Code Implementierung:Quellcode von HTML-Datei python3.1 urllib.request

import urllib.request 
def extract_words(wdict, urlname): 
    uf = urllib.request.urlopen(urlname) 
    text = uf.read() 
    print (text) 
    match = re.findall("<tr>\s*<td>([\w\s.;'(),-/]+)</td>\s+<td>([\w\s.,;'()-/]+)</td>\s*</tr>", text) 

, die einen Fehler zurückgibt:

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 

bei der weiteren in den IDLE experimentieren, bemerkte ich, dass die uf.read() in der Tat den hTML-Quellcode gibt das erste Mal, dass ich es aufrufen. Aber dann gibt es a - b zurück. Gibt es eine Möglichkeit, dies zu umgehen?

Antwort

2

uf.read() liest den Inhalt nur einmal. Dann müssen Sie es schließen und erneut öffnen, um es erneut zu lesen. Dies gilt für jede Art von Stream. Dies ist jedoch nicht das Problem.

Das Problem besteht darin, dass beim Lesen von jeder Art von Binärquelle, z. B. einer Datei oder einer Webseite, die Daten als bytes-Typ zurückgegeben werden, sofern Sie keine Codierung angeben. Aber Ihre Regexp ist nicht als bytes Typ angegeben, es ist als Unicode str angegeben.

Das re-Modul wird recht vernünftig weigern, Unicode-Muster auf Byte-Daten zu verwenden, und umgekehrt.

Die Lösung besteht darin, das Regexp-Muster zu einer Bytes-Zeichenfolge zu machen, indem Sie ein b davor setzen. Daher:

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

Sollte funktionieren. Eine weitere Möglichkeit ist, den Text zu entschlüsseln, so dass es auch ein Unicode ist 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) 

(, auch Daten aus HTML zu extrahieren, ich würde sagen, dass lxml ist eine bessere Option).