2013-06-29 17 views
6

EDIT: ho capito il problema. Il # in #user_sex non viene convertito in% 23 da richieste python. C'è un modo per forzare le richieste Python per convertire # in% 23 o devo semplicemente codificare quella parte?Python richiede che urlencode non funzioni?

Sto provando a creare una follia di facebook fql. Quando uso il fql_url sotto

fql_url = (
    'https://graph.facebook.com/fql?q=' 
    '{"user_sex":"SELECT sex FROM user WHERE uid=me()",' 
    '"friends":"SELECT uid, name FROM user WHERE uid IN ' 
    '(SELECT uid2 FROM friend WHERE uid1 = me()) ' 
    'AND not (sex in (SELECT sex FROM #user_sex)) ' 
    ' ORDER BY name"}' 
    '&access_token='+access_token 
) 

e corro requests.get (fql_url), il JSON restituito è

{u'error': { 
    u'code': 601, 
    u'message': u"(#601) Parser error: unexpected '{' at position 0.", 
    u'type': u'OAuthException'} 
} 

Tuttavia quando ho la mano il codice fql_url come questo

fql_url = (
    'https://graph.facebook.com/fql?q=%7B%22' 
    'user_sex%22:%22SELECT%20sex%20FROM%20user%20WHERE%20uid=me()%22,%22' 
    'friends%22:%22SELECT%20uid,%20name%20FROM%20user%20WHERE%20uid%20IN%20' 
    '(SELECT%20uid2%20FROM%20friend%20WHERE%20uid1%20=%20me())%20' 
    'AND%20not%20(sex%20in%20(select%20sex%20from%20%23user_sex))%20%20' 
    'ORDER%20BY%20name%22%7D&' 
    'access_token='+access_token 
) 

tutto funziona (il json ha i dati desiderati).

Ho confrontato sia il primo fql_url che il codice fql_url codificato a mano ed entrambi dovrebbero generare lo stesso url utilizzato per ottenere il json. L'urlencode delle richieste non funziona o sto facendo qualcosa di sbagliato qui?

risposta

12

Il problema è, che # è davvero un carattere valido in un URL. Denota la parte del frammento. Poiché il frammento viene sempre risolto dall'utente user non viene mai inviato al server. Si può provare questo:

>>> import urllib3 
>>> urllib3.util.parse_url(fql_url) 
Url(scheme='https', auth=None, host='graph.facebook.com', port=None, path='/fql', 
    query='q={"user_sex":"SELECT sex FROM user WHERE uid=me()","friends":"SELECT uid, name FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()) AND not (sex in (SELECT sex FROM ', 
    fragment='user_sex)) ORDER BY name"}') 

Come si può vedere, l'ultima parte del tuo URL finito per essere analizzato come il frammento.

Edit:

Il modo più conveniente sarebbe probabilmente di lasciare che le richieste di fare tutto il codifica.

import requests 
s = requests.Session() 
s.params = {'access_token': 'foobarbaz'} # so you don't have to specify it every time 
query = ('{"user_sex":"SELECT sex FROM user WHERE uid=me()",' 
     '"friends":"SELECT uid, name FROM user WHERE uid IN ' 
     '(SELECT uid2 FROM friend WHERE uid1 = me()) ' 
     'AND not (sex in (SELECT sex FROM #user_sex)) ' 
     ' ORDER BY name"}') 
s.get('https://graph.facebook.com/fql', params={'q': query}) 
+0

Questo ha senso. Quindi in pratica dovrei usare il primo fql_url e sostituire semplicemente # con% 23 o c'è un modo più convenzionale di farlo? – bab

+1

Ho aggiunto il modo pragmatico di rispondermi –

3

Utilizzare urllib.quote() prima della chiamata urlopen.

  1. Se si utilizza urllib.urlencode correttamente sembra codificare # in %23.
  2. Se sei mai bloccato con caratteri non validi, citali (e se hai bisogno di citare il '+', usa quote_plus).
  3. si può sempre provare a riga di comando:

$ d={'e':'e^&*F##'} $ urllib.urlencode(d) -> 'e=e%5E%26%2AF%23%23'

Nota che # ->%23

+0

Questo funziona, ma perché è necessario chiamarlo? Le richieste non gestiscono già la conversione? – bab

+0

Se si utilizza urllib.urlencode correttamente sembra codificare # in% 23; ma dal momento che quel codice non era qui non potrei dire da dove provenga l'errore. Se sei mai bloccato con caratteri non validi, citali (e se hai bisogno di citare il '+', usa quote_plus). Si può sempre provare a riga di comando: >>> d = { 'e': 'e^& * F ##'} >>> urllib.urlencode (d) 'e = e% 5E% 26 % 2AF% 23% 23 ' Si noti che # ->% 23 –

+1

Ok, grazie, lo userò per ora. Ma sai perché le richieste non lo codificano correttamente? Questa è la biblioteca a cui mi riferisco. http: // docs.python-requests.org/en/latest/ – bab

Problemi correlati