2010-11-27 6 views
2

Hey Jungs, ich bin nur der Google App Engine zu lernen so in eine Reihe von Problemen, die ich bin mit ...urllib2, Google App Engine und Unicode Frage

Meine derzeitige Situation ist dies. Ich habe eine Datenbank,

class Website(db.Model): 
    web_address = db.StringProperty() 
    company_name = db.StringProperty() 
    content = db.TextProperty() 
    div_section = db.StringProperty() 
    local_links = db.StringProperty() 
    absolute_links = db.BooleanProperty() 
    date_updated = db.DateTimeProperty() 

und das Problem, das ich habe, ist mit der Inhaltseigenschaft.

Ich benutze die db.TextProperty(), weil ich den Inhalt einer Webseite speichern muss, die> 500 Bytes haben.

Das Problem, in das ich laufe, ist urllib2.readlines() formatiert als Unicode. Beim Einfügen in eine TextProperty() wird in ASCII konvertiert. einige der Zeichen sind> 128 und es wirft einen UnicodeDecodeError.

Gibt es eine einfache Möglichkeit, dies zu umgehen? Zum größten Teil, es ist mir egal über jene Zeichen ...

mein Fehler ist:

Traceback (most recent call last):
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/init.py", line 511, in call handler.get(*groups) File "/base/data/home/apps/game-job-finder/1.346504560470727679/main.py", line 61, in get x.content = website_data_joined File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/init.py", line 542, in set value = self.validate(value) File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/init.py", line 2407, in validate value = self.data_type(value) File "/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore_types.py", line 1006, in new return super(Text, cls).new(cls, arg, encoding) UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 2124: ordinal not in range(128)

+1

ich Unicode hätte gedacht, zu ASCII, dass die Umwandlung wäre „kodiert“, nicht „Decodierung ". Bist du sicher, dass es nicht umgekehrt ist? –

+0

ja, du hast Recht. – shawn

+0

könnten Sie das Snippet hinzufügen, in dem Sie die readline erstellen und den Datenspeicher anlegen? – systempuntoout

Antwort

1

Es scheint, dass die Linien zurück von readlines sind nicht Unicode-Strings, sondern Byte-Strings (dh Instanzen von str, die möglicherweise Nicht-ASCII-Zeichen enthalten). Diese Bytes sind die Rohdaten, die im HTTP-Response-Body empfangen werden, und stellen abhängig von der verwendeten Codierung unterschiedliche Strings dar. Sie müssen "decodiert" werden, bevor sie als Text behandelt werden können (Bytes! = Zeichen).

Wenn die Kodierung UTF-8, soll dieser Code ordnungsgemäß funktionieren:

f = urllib2.open('http://www.google.com') 
website = Website() 
website.content = db.Text(f.read(), encoding = 'utf-8-sig') # 'sig' deals with BOM if present 

Beachten Sie, dass die tatsächliche Codierung von Website zu Website unterschiedlich (manchmal auch von Seite zu Seite). Die verwendete Kodierung sollte in der HTTP-Antwort in den Content-Type-Header aufgenommen werden (siehe this question), wenn dies nicht der Fall ist, kann sie in einem Meta-Tag im Kopf des HTML-Codes enthalten sein (in diesem Fall das Extrahieren) richtig ist viel komplizierter):

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

Beachten Sie, dass es Seiten gibt, die keine Kodierung angeben oder die falsche Codierung angeben.

Wenn Sie wirklich alle Zeichen nicht kümmern, aber ASCII, Sie können sie ignorieren und mit ihm getan werden:

f = urllib2.open('http://www.google.com') 
website = Website() 
content = unicode(f.read(), errors = 'ignore') # Ignore characters that cause errors 
website.content = db.Text(content) # Don't need to specify an encoding since content is already a unicode string