2013-06-29 4 views
6

EDIT: Ich habe das Problem herausgefunden. # In #user_sex wird nicht durch Python-Anfragen in% 23 konvertiert. Gibt es eine Möglichkeit, Python-Anfragen zu erzwingen, # zu% 23 zu konvertieren, oder muss ich diesen Teil nur manuell programmieren?Python fordert Urlencode nicht funktioniert?

Ich versuche, eine facebook fql multiquery zu machen. Als ich die fql_url unter

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 
) 

verwenden und führen requests.get (fql_url) kehrte die json ist

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

Jedoch, wenn ich Code von Hand die fql_url als dieser

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 
) 

alles funktioniert (der JSON hat die gewünschten Daten).

Ich habe sowohl die erste fql_url und die Hand codiert fql_url verglichen und beide sollten dazu führen, dass die gleiche URL verwendet wird, um die JSON zu bekommen. Funktioniert der Urlencode nicht oder mache ich hier etwas falsch?

Antwort

12

Das Problem ist, dass # in einer URL in der Tat ein gültiges Zeichen ist. Es bezeichnet den Fragmentteil. Da das Fragment immer vom Useragent aufgelöst wird, wird es niemals an den Server gesendet. Sie können dies versuchen:

>>> 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"}') 

Wie Sie der letzte Teil der URL sehen können, endete als als Fragment analysiert.

Edit:

Der bequemste Weg wäre wahrscheinlich Anfragen alle die Codierung tun zu lassen.

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

Das macht Sinn. Also sollte ich grundsätzlich die erste fql_url verwenden und # durch% 23 ersetzen oder gibt es eine konventionellere Methode? – bab

+1

Ich habe den pragmatischen Weg zu mir hinzugefügt –

3

Verwenden Sie urllib.quote() vor Ihrem urlopen Anruf.

  1. Wenn Sie mit urllib.urlencode richtig scheint es # in %23 zu kodieren.
  2. Wenn Sie jemals mit ungültigen Zeichen festgefahren sind, zitieren Sie sie (und wenn Sie das '+' zitieren müssen, verwenden Sie quote_plus).
  3. Sie können jederzeit in der Befehlszeile versuchen:

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

Beachten Sie, dass # ->%23

+0

Das funktioniert, aber warum muss ich es nennen? Erfüllen Anfragen nicht bereits die Konvertierung? – bab

+0

Wenn Sie urllib.urlencode richtig verwenden, scheint es # in% 23 zu kodieren; Aber da dieser Code nicht hier war, konnte ich nicht sagen, woher der Fehler kommt. Wenn Sie jemals mit ungültigen Zeichen beschäftigt sind, zitieren Sie sie (und wenn Sie das '+' zitieren müssen, verwenden Sie quote_plus). Sie können jederzeit in der Befehlszeile versuchen: >>> d = { 'e': 'e^& * F ##'} >>> urllib.urlencode (d) ‚e = e% 5E% 26 % 2AF% 23% 23 ' Beachten Sie, dass # ->% 23 –

+1

Ok danke ich werde das für jetzt verwenden. Aber wissen Sie, warum Anfragen es nicht richtig codieren? Dies ist die Bibliothek, auf die ich mich beziehe. http: // Dokumentepython-requests.org/en/latest/ – bab