web-dev-qa-db-fra.com

Python Demande l'encodage POST data

Version: Python 2.7.3

Autres bibliothèques: Python-Requests 1.2.3, jinja2 (2.6)

J'ai un script qui soumet des données à un forum et le problème est que les caractères non-ascii apparaissent comme des ordures. Par exemple, un nom comme André Téchiné sort comme André Tà © chinà ©.

Voici comment les données sont soumises:

1) Les données sont initialement chargées à partir d'un fichier CSV codé UTF-8 comme suit:

entries = []
with codecs.open(filename, 'r', 'utf-8') as f:
    for row in unicode_csv_reader(f.readlines()[1:]):
        entries.append(dict(Zip(csv_header, row)))

unicode_csv_reader provient du bas de la page de documentation Python CSV: http://docs.python.org/2/library/csv.html

Lorsque je tape le nom des entrées dans l'interpréteur, je vois le nom comme u'Andr\xe9 T\xe9chin\xe9'.

2) Ensuite, je rend les données via jinja2:

tpl = tpl_env.get_template(u'forumpost.html')
rendered = tpl.render(entries=entries)

Quand je tape le nom rendu dans l'interpréteur je revois le même: u'Andr\xe9 T\xe9chin\xe9'

Maintenant, si j'écris la variable rendue dans un nom de fichier comme celui-ci, elle s'affiche correctement:

with codecs.open('out.txt', 'a', 'utf-8') as f:
    f.write(rendered)

Mais je dois l'envoyer sur le forum:

3) Dans le code de demande POST j'ai:

params = {u'post': rendered}
headers = {u'content-type': u'application/x-www-form-urlencoded'}
session.post(posturl, data=params, headers=headers, cookies=session.cookies)

session est une session Requests.

Et le nom est affiché cassé dans le post du forum. J'ai essayé ce qui suit:

  • Omettre les en-têtes
  • Encode rendu en rendu.encode ('utf-8') (même résultat)
  • rendu = urllib.quote_plus (rendu) (apparaît comme tous les% XY)

Si je tape rendu.encode ('utf-8'), je vois ce qui suit:

'Andr\xc3\xa9 T\xc3\xa9chin\xc3\xa9'

Comment pourrais-je résoudre le problème? Merci.

21
TheMagician

Votre client se comporte comme il se doit, par exemple fonctionnement nc -l 8888 en tant que serveur et en faisant une demande:

import requests

requests.post('http://localhost:8888', data={u'post': u'Andr\xe9 T\xe9chin\xe9'})

spectacles:

POST / HTTP/1.1
Host: localhost:8888
Content-Length: 33
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate, compress
Accept: */*
User-Agent: python-requests/1.2.3 CPython/2.7.3

post=Andr%C3%A9+T%C3%A9chin%C3%A9

Vous pouvez vérifier qu'il est correct:

>>> import urllib
>>> urllib.unquote_plus(b"Andr%C3%A9+T%C3%A9chin%C3%A9").decode('utf-8')
u'Andr\xe9 T\xe9chin\xe9'
  • vérifiez que le serveur décode correctement la demande. Vous pouvez essayer de spécifier le jeu de caractères:

    headers = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
    

    le corps ne contient que des caractères ascii donc cela ne devrait pas faire de mal et le bon serveur ignorerait tous les paramètres pour x-www-form-urlencoded tapez quand même. Recherchez des détails sanglants dans données de formulaire encodées en URL

  • vérifier que le problème n'est pas un artefact d'affichage, c'est-à-dire que la valeur est correcte mais qu'elle ne s'affiche pas correctement

28
jfs

Essayez de décoder en utf8:

unicode(my_string_variable, "utf8")

ou décoder et encoder:

sometext = gettextfromsomewhere().decode('utf-8')
env = jinja2.Environment(loader=jinja2.PackageLoader('jinjaapplication', 'templates'))
template = env.get_template('mypage.html')
print template.render( sometext = sometext ).encode('utf-8')
2
dikkini