【问题标题】:Python-Requests, extract url parameters from a stringPython-Requests,从字符串中提取url参数
【发布时间】:2015-04-04 10:02:27
【问题描述】:

我正在使用这个很棒的库 requests 来维护 python 2 和 3 的兼容性并简化我的应用程序请求管理。

我有一个案例,我需要解析一个 url 并替换它的一个参数。例如:

http://example.com?param1=a&token=TOKEN_TO_REPLACE&param2=c

我想得到这个:

http://example.com?param1=a&token=NEW_TOKEN&param2=c

有了urllib,我可以这样实现:

from urllib.parse import urlparse
from urllib.parse import parse_qs
from urllib.parse import urlencode

url = 'http://example.com?param1=a&token=TOKEN_TO_REPLACE&param2=c'

o = urlparse(url)
query = parse_qs(o.query)
if query.get('token'):
    query['token'] = ['NEW_TOKEN', ]
    new_query = urlencode(query, doseq=True)
    url.split('?')[0] + '?' + new_query

>>> http://example.com?param2=c&param1=a&token=NEW_TOKEN

您如何使用requests 库实现相同的目标?

【问题讨论】:

    标签: python python-3.x python-requests


    【解决方案1】:

    您不能为此使用requests;如果为参数传递了 Python 结构,则库 构建 此类 URL,但不提供任何工具来解析它们。这不是该项目的目标。

    坚持urllib.parse方法解析出参数。有了字典或键值元组列表后,只需将其传递给 requests 即可再次构建 URL:

    try:
        # Python 3
        from urllib.parse import urlparse, parse_qs
    except ImportError:
        # Python 2
        from urlparse import urlparse, parse_qs
    
    o = urlparse(url)
    query = parse_qs(o.query)
    # extract the URL without query parameters
    url = o._replace(query=None).geturl()
    
    if 'token' in query:
        query['token'] = 'NEW_TOKEN'
    
    requests.get(url, params=query)
    

    urlparseparse_qs 函数在 Python 2 和 3 中都可以获取,如果遇到异常,只需调整导入位置即可。

    在 Python 3 上的演示(没有导入异常保护)来演示 URL 已构建:

    >>> from urllib.parse import urlparse, parse_qs
    >>> url = "http://httpbin.org/get?token=TOKEN_TO_REPLACE&param2=c"
    >>> o = urlparse(url)
    >>> query = parse_qs(o.query)
    >>> url = o._replace(query=None).geturl()
    >>> if 'token' in query:
    ...     query['token'] = 'NEW_TOKEN'
    ... 
    >>> response = requests.get(url, params=query)
    >>> print(response.text)
    {
      "args": {
        "param2": "c", 
        "token": "NEW_TOKEN"
      }, 
      "headers": {
        "Accept": "*/*", 
        "Accept-Encoding": "gzip, deflate", 
        "Host": "httpbin.org", 
        "User-Agent": "python-requests/2.5.1 CPython/3.4.2 Darwin/14.1.0"
      }, 
      "origin": "188.29.165.245", 
      "url": "http://httpbin.org/get?token=NEW_TOKEN&param2=c"
    }
    

    【讨论】:

    • @Gab:我已经更新了这篇文章,以阐明如何保持 Python 2 和 3 之间的兼容性;两个版本中都存在相同的功能,只是在不同的位置。 requests 对此无能为力。
    • 实际上,我更详细地检查了请求网站和 github 文件夹,看来您是对的。 +1 最后使用requests 库显示代码的简化版本!
    • Martijn,你应该更新这个答案。此函数可作为 requests.utils.urlparse 使用(实际上是相同的函数,它来自 compat which comes from this file)并且我认为自 2017 年以来一直存在。
    • @Boris requests.compat 模块不是公共 API 的一部分。它基本上完成了我的回答,但这并不意味着您可以依靠它继续这样做。它只被导入requests.utils,因为该模块中的实现需要它。换句话说,它存在的唯一原因是作为实现细节
    • @MartijnPieters 我不确定。据我所知,该模块中的所有功能都没有记录,但它说“该模块提供了在请求中使用的实用功能,也可用于外部消费”。我想如果这是他们将用下划线导入的想法import urlparse as _urlparse
    【解决方案2】:

    仅使用requests

    query = requests.utils.urlparse(url).query
    params = dict(x.split('=') for x in query.split('&'))
    
    if 'token' in params:
        params['token'] = 'NEW_TOKEN'
    
    requests.get(url, params=params)
    

    【讨论】:

    • 我认为可能还需要requests.utils.unquote,以防止发送空格、“%20”等字符。
    猜你喜欢
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 2011-08-30
    • 1970-01-01
    相关资源
    最近更新 更多