2010-11-27 8 views
2

Hé les gars, je suis en train d'apprendre le moteur app google donc je suis en cours d'exécution dans un tas de problèmes ...urllib2, Google App Engine, et unicode question

Ma situation actuelle est la suivante. J'ai une base de données,

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() 

et le problème que j'ai est avec la propriété de contenu. J'utilise db.TextProperty() parce que j'ai besoin de stocker le contenu d'une page web qui a> 500 octets.

Le problème que je rencontre est urllib2.readlines() formats comme unicode. Lors de la mise dans un TextProperty(), il convertit en ASCII. certains des caractères sont> 128 et il lance un UnicodeDecodeError.

Existe-t-il un moyen simple de contourner cela? Pour la plupart, je ne me soucie pas de ces personnages ...

mon erreur est:

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

j'aurais pensé que la conversion Unicode en ASCII serait « coder » décodage non » ". Êtes-vous sûr que ce n'est pas l'inverse? –

+0

oui, vous avez raison. – shawn

+0

pourriez-vous ajouter l'extrait où vous faites la readline et mettre sur le magasin de données? – systempuntoout

Répondre

1

Il semblerait que les lignes de retour readlines ne sont pas des chaînes unicode, mais plutôt des chaînes d'octets (c'est-à-dire des instances de str contenant des caractères potentiellement non-ASCII). Ces octets sont les données brutes reçues dans le corps de la réponse HTTP et représenteront différentes chaînes en fonction du codage utilisé. Ils doivent être "décodés" avant de pouvoir être traités comme du texte (octets! = Caractères).

Si l'encodage est UTF-8, ce code devrait fonctionner correctement:

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 

Notez que le codage réel varie d'un site Internet (parfois même d'une page à). L'encodage utilisé doit être inclus dans l'en-tête Content-Type de la réponse HTTP (voir this question pour savoir comment l'obtenir), mais si ce n'est pas le cas, il peut être inclus dans une méta-balise HTML (dans ce cas, extraire est bien beaucoup plus difficile):

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

Notez qu'il existe des sites qui ne spécifient pas un codage ou de spécifier le mauvais codage.

Si vraiment vous ne se soucient pas des caractères ASCII mais, vous pouvez les ignorer et faire avec elle:

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