【问题标题】:Python requests urlencode not working?Python 请求 urlencode 不起作用?
【发布时间】:2013-06-26 20:54:50
【问题描述】:

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

我正在尝试制作一个 facebook fql 多查询。当我使用下面的 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 不起作用还是我在这里做错了什么?

【问题讨论】:

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


    【解决方案1】:

    在调用urlopen 之前使用urllib.quote()

    1. 如果您正确使用urllib.urlencode,它似乎将# 编码为%23
    2. 如果您遇到过无效字符,请引用它们(如果您需要引用“+”,请使用 quote_plus)。
    3. 您可以随时在命令行尝试:

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

    注意# -> %23

    【讨论】:

    • 这行得通,但为什么我需要调用它?请求不是已经处理转换了吗?
    • 如果您正确使用 urllib.urlencode 它似乎将 # 编码为 %23;但由于该代码不在这里,我无法判断您的错误来自哪里。如果您遇到无效字符,请引用它们(如果您需要引用'+',请使用quote_plus)。您可以随时在命令行尝试: >>> d={'e':'e^&*F##'} >>> urllib.urlencode(d) 'e=e%5E%26%2AF%23% 23' 请注意 # -> %23
    • 好的,谢谢,我现在就使用它。但是你知道为什么 requests 没有正确编码吗?这是我指的图书馆。 docs.python-requests.org/en/latest
    • @bab :我面临同样的问题。你有什么解决办法吗?
    【解决方案2】:

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

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

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

    编辑:

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

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

    【讨论】:

    • 这是有道理的。所以基本上我应该使用第一个 fql_url 并将 # 替换为 %23 还是有更传统的方法来做到这一点?
    • 我给我加了务实的回答方式
    猜你喜欢
    • 2019-06-21
    • 1970-01-01
    • 2018-04-10
    • 1970-01-01
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 2022-01-15
    相关资源
    最近更新 更多