2012-04-14 18 views
8

trato de publicar datos Unicode con la función httplib.request:¿Cómo publico caracteres Unicode usando httplib?

s = u"עברית" 
data = """ 
<spellrequest textalreadyclipped="0" ignoredups="1" ignoredigits="1" ignoreallcaps="0"> 
<text>%s</text> 
</spellrequest> 
""" % s 

con = httplib.HTTPSConnection("www.google.com") 
con.request("POST", "/tbproxy/spell?lang=he", data) 
response = con.getresponse().read() 

Sin embargo, este es mi error:

Traceback (most recent call last): 
    File "C:\Scripts\iQuality\test.py", line 47, in <module> 
    print spellFix(u"╫á╫נ╫¿╫ץ╫ר╫ץ") 
    File "C:\Scripts\iQuality\test.py", line 26, in spellFix 
    con.request("POST", "/tbproxy/spell?lang=%s" % lang, data) 
    File "C:\Python27\lib\httplib.py", line 955, in request 
    self._send_request(method, url, body, headers) 
    File "C:\Python27\lib\httplib.py", line 989, in _send_request 
    self.endheaders(body) 
    File "C:\Python27\lib\httplib.py", line 951, in endheaders 
    self._send_output(message_body) 
    File "C:\Python27\lib\httplib.py", line 815, in _send_output 
    self.send(message_body) 
    File "C:\Python27\lib\httplib.py", line 787, in send 
    self.sock.sendall(data) 
    File "C:\Python27\lib\ssl.py", line 220, in sendall 
    v = self.send(data[count:]) 
    File "C:\Python27\lib\ssl.py", line 189, in send 
    v = self._sslobj.write(data) 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 97-102: or 
dinal not in range(128) 

¿Dónde estoy mal?

Respuesta

9

http no se define en términos de una codificación de caracteres particular, y en su lugar utiliza octetos. Necesita convertir sus datos a una codificación, y luego debe decirle al servidor qué codificación ha utilizado. Permite usar utf8, ya que generalmente es la mejor opción:

Esta información se parece un poco a XML, pero se está saltando la etiqueta xml. Algunos servicios pueden aceptar eso, pero no deberías hacerlo de todos modos. De hecho, la codificación en realidad pertenece allí; así que asegúrate de incluirlo. El encabezado se ve como <?xml version="1.0" encoding="que codifica"?>.

s = u"עברית" 
data_unicode = u"""<?xml version="1.0" encoding="UTF-8"?> 
<spellrequest textalreadyclipped="0" ignoredups="1" ignoredigits="1" ignoreallcaps="0"> 
<text>%s</text> 
</spellrequest> 
""" % s 

data_octets = data_unicode.encode('utf-8') 

Como una cuestión de cortesía, también debe decirle al servidor en sí el formato y la codificación, con el encabezado content-type:

con = httplib.HTTPSConnection("www.google.com") 
con.request("POST", 
      "/tbproxy/spell?lang=he", 
      data_octets, {'content-type': 'text/xml; charset=utf-8'}) 

EDIT: Está funcionando bien en mi máquina, ¿está seguro de que ¿No estás salteando algo? Ejemplo completo

>>> from cgi import escape 
>>> from urllib import urlencode 
>>> import httplib 
>>> 
>>> template = u"""<?xml version="1.0" encoding="UTF-8"?> 
... <spellrequest textalreadyclipped="0" ignoredups="1" ignoredigits="1" ignoreallcaps="0"> 
... <text>%s</text> 
... </spellrequest> 
... """ 
>>> 
>>> def chkspell(word, lang='en'): 
...  data_octets = (template % escape(word)).encode('utf-8') 
...  con = httplib.HTTPSConnection("www.google.com") 
...  con.request("POST", 
...   "/tbproxy/spell?" + urlencode({'lang': lang}), 
...   data_octets, 
...   {'content-type': 'text/xml; charset=utf-8'}) 
...  req = con.getresponse() 
...  return req.read() 
... 
>>> chkspell('baseball') 
'<?xml version="1.0" encoding="UTF-8"?><spellresult error="0" clipped="0" charschecked="8"></spellresult>' 
>>> chkspell(corpus, 'he') 
'<?xml version="1.0" encoding="UTF-8"?><spellresult error="0" clipped="0" charschecked="5"></spellresult>' 

me di cuenta de que cuando me pega tu ejemplo, que aparece en el orden opuesto en mi terminal de cómo se muestra en el navegador. No es demasiado sorprendente teniendo en cuenta que el hebreo es un idioma de derecha a izquierda.

>>> corpus = u"עברית" 
>>> print corpus[0] 
ע 
+2

Omitir la declaración XML está bien. Solo lo necesita cuando desea una codificación que no sea UTF o XML 1.1. – bobince

+0

Google realmente devuelve un error si envía la declaración XML. – iTayb

+0

@iTayb: ¿Cómo se ve el error? Funcionó bien en mi máquina. – SingleNegationElimination