Python请求urlencode无法正常工作?

时间:2013-06-29 00:50:45

标签: python facebook url facebook-fql python-requests

编辑:我发现了问题所在。 #user_sex中的#没有被python请求转换为%23。有没有办法强制python请求将#转换为%23或者我只需要手动编写那部分代码?

我正在尝试制作一个facebook fql multiquery。当我使用下面的fql_url时

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
)

并运行requests.get(fql_url),返回的json是

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

然而,当我手动将fql_url编码为

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
)

一切正常(json有所需的数据)。

我比较了第一个fql_url和手动编码的fql_url,两者都应该导致使用相同的url来获取json。请求urlencode不起作用还是我在这里做错了什么?

2 个答案:

答案 0 :(得分:12)

问题是,#确实是URL中的有效字符。它表示片段部分。 由于片段始终由useragent解析,因此永远不会将其发送到服务器。 你可以试试这个:

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

如您所见,您网址的最后一部分最终被解析为片段。

编辑:

最方便的方法可能是让请求执行所有编码。

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

答案 1 :(得分:3)

urllib.quote()来电之前使用urlopen

  1. 如果您正确使用urllib.urlencode,它似乎会将#编码为%23
  2. 如果您遇到无效的字符,请引用它们(如果您需要引用'+',请使用quote_plus)。
  3. 您可以随时尝试使用命令行:
  4. $ d={'e':'e^&*F##'} $ urllib.urlencode(d) -> 'e=e%5E%26%2AF%23%23'

    请注意# - > %23