2009-06-20 11 views
45

Ich muss den Inhalt einer Website speichern, die in jeder Sprache sein kann. Und ich muss in der Lage sein, den Inhalt nach einer Unicode-Zeichenkette zu durchsuchen.urllib2 gelesen zu Unicode

Ich habe versucht, so etwas wie:

import urllib2 

req = urllib2.urlopen('http://lenta.ru') 
content = req.read() 

Der Inhalt ist ein Byte-Strom, also kann ich es für eine Unicode-Zeichenfolge suchen.

Ich brauche eine Möglichkeit, wenn ich urlopen tun und dann lesen, um den Zeichensatz aus den Headern zu verwenden, um den Inhalt zu dekodieren und es in UTF-8 zu kodieren.

+0

Die Codierung erfolgt mit einer Funktion aus der Urllib-Bibliothek nicht von Urllib2. Von http://www.voidspace.org.uk/python/articles/urllib2.shtml#headers – Macarse

+1

@Macarse ist dies nicht die Kodierung, auf die sich Vitaly bezieht, er bezieht sich auf das Entschlüsseln und Kodieren des tatsächlichen Anforderungskontexts mit '[byte string] '. decode (' [Zeichensatz] ') und u' [Unicode-Zeichensatz] '. encode (' utf-8 '). Sie beziehen sich auf Parameter für die Kodierungsanfrage. –

+0

verwandt: [Eine gute Möglichkeit, den Zeichensatz/die Codierung einer HTTP-Antwort in Python zu erhalten] (http://stackoverflow.com/q/14592762/4279) – jfs

Antwort

96

Nach den Operationen, die Sie durchgeführt, werden Sie sehen:

>>> req.headers['content-type'] 
'text/html; charset=windows-1251' 

und so:

>>> encoding=req.headers['content-type'].split('charset=')[-1] 
>>> ucontent = unicode(content, encoding) 

ucontent ist nun eine Unicode-Zeichenfolge (von 140.655 Zeichen) - so zum Beispiel angezeigt werden ein Teil davon, wenn Ihr Terminal ist UTF-8:

>>> print ucontent[76:110].encode('utf-8') 
<title>Lenta.ru: Главное: </title> 

und Sie können suchen, etc, etc.

Bearbeiten: Unicode-I/O ist in der Regel schwierig (das kann sein, was den ursprünglichen Asker hält), aber ich werde das schwierige Problem der Eingabe von Unicode-Zeichenfolgen zu einem interaktiven Python-Interpreter umgehen (völlig unabhängig von der ursprünglichen Frage)) um zu zeigen, wie, sobald ein Unicode String richtig eingegeben wird (ich mache es mit Codepoints - doof aber nicht knifflig ;-), ist die Suche absolut ein Kinderspiel (und hoffentlich wurde die ursprüngliche Frage gründlich beantwortet). Wieder einen UTF-8-Terminal unter der Annahme:

>>> x=u'\u0413\u043b\u0430\u0432\u043d\u043e\u0435' 
>>> print x.encode('utf-8') 
Главное 
>>> x in ucontent 
True 
>>> ucontent.find(x) 
93 

Hinweis: Beachten Sie, dass diese Methode nicht für alle Standorte arbeiten kann, da nur einige Websites Zeichenkodierung innerhalb der bedient Dokumente angeben (mit http-equiv Meta-Tags , beispielsweise).

+0

Hey Alex, danke für die Antwort. Aber wenn ich: u'Главное 'in UContent gibt es False zurück. Gibt es eine bessere Möglichkeit, die Suche durchzuführen? –

+2

Wie gibst du diese Zeichenfolge ein? Unicode-I/O ist schwierig, da Ihr Terminal UND Python auf identischen Wellenlängen liegen muss. Die Verwendung von expliziten Unicode-Codepoints (langweilig, aber nicht knifflig) funktioniert gut, lassen Sie mich meine Antwort bearbeiten, um das zu zeigen. –

+0

Ich benutze die Konsole, wenn ich dies für einen Komponententest tun soll, was sollte ich die Codierung einstellen: an der Spitze der Datei? –

9

Content-Type HTTP-Header zu analysieren, können Sie cgi.parse_header Funktion:

>>> import urllib2 
>>> r = urllib2.urlopen('http://lenta.ru') 
>>> r.headers.getparam('charset') 
'utf-8' 

Oder in Python 3:

>>> import urllib.request 
>>> r = urllib.request.urlopen('http://lenta.ru') 
>>> r.headers.get_content_charset() 
'utf-8' 

Charakter

import cgi 
import urllib2 

r = urllib2.urlopen('http://lenta.ru') 
_, params = cgi.parse_header(r.headers.get('Content-Type', '')) 
encoding = params.get('charset', 'utf-8') 
unicode_text = r.read().decode(encoding) 

Ein anderer Weg, um die charset zu erhalten Die Codierung kann auch im HTML-Dokument angegeben werden, zB <meta charset="utf-8">.