在 Python 中向给定的 URL 添加参数

2025-03-04 08:27:00
admin
原创
76
摘要:问题描述:假设我获得了一个 URL。 它可能已经包含 GET 参数(例如http://example.com/search?q=question),也可能不包含(例如http://example.com/)。现在我需要添加一些参数,例如{'lang':'en','tag':'python'}。在第一种情况下...

问题描述:

假设我获得了一个 URL。

它可能已经包含 GET 参数(例如http://example.com/search?q=question),也可能不包含(例如http://example.com/)。

现在我需要添加一些参数,例如{'lang':'en','tag':'python'}。在第一种情况下,我将使用;http://example.com/search?q=question&lang=en&tag=python在第二种情况下,我将使用 — http://example.com/search?lang=en&tag=python

有没有什么标准的方法可以做到这一点?


解决方案 1:

urllib和模块有几个怪癖urlparse。这是一个工作示例:

try:
    import urlparse
    from urllib import urlencode
except: # For Python 3
    import urllib.parse as urlparse
    from urllib.parse import urlencode

url = "http://stackoverflow.com/search?q=question"
params = {'lang':'en','tag':'python'}

url_parts = list(urlparse.urlparse(url))
query = dict(urlparse.parse_qsl(url_parts[4]))
query.update(params)

url_parts[4] = urlencode(query)

print(urlparse.urlunparse(url_parts))

ParseResult`urlparse(),的结果是只读的,我们需要将其转换为,list`然后才能尝试修改其数据。

解决方案 2:

将其外包给经过实战测试的请求库。

我会这样做:

from requests.models import PreparedRequest
url = 'http://example.com/search?q=question'
params = {'lang':'en','tag':'python'}
req = PreparedRequest()
req.prepare_url(url, params)
print(req.url)

解决方案 3:

为什么

我对本页上的所有解决方案都不满意(拜托,我们最喜欢的复制粘贴东西在哪里?),所以我根据这里的答案编写了自己的解决方案。它试图完整且更具 Python 风格。我在参数中添加了dictbool值的处理程序,以便对消费者端(JS)更加友好,但它们仍然是可选的,您可以删除它们。

工作原理

测试 1:添加新参数,处理数组和布尔值:

url = 'http://stackoverflow.com/test'
new_params = {'answers': False, 'data': ['some','values']}

add_url_params(url, new_params) == \n    'http://stackoverflow.com/test?data=some&data=values&answers=false'

测试 2:重写现有参数,处理 DICT 值:

url = 'http://stackoverflow.com/test/?question=false'
new_params = {'question': {'__X__':'__Y__'}}

add_url_params(url, new_params) == \n    'http://stackoverflow.com/test/?question=%7B%22__X__%22%3A+%22__Y__%22%7D'

说话没那么容易。给我看代码。

代码本身。我尝试详细描述它:

from json import dumps

try:
    from urllib import urlencode, unquote
    from urlparse import urlparse, parse_qsl, ParseResult
except ImportError:
    # Python 3 fallback
    from urllib.parse import (
        urlencode, unquote, urlparse, parse_qsl, ParseResult
    )


def add_url_params(url, params):
    """ Add GET params to provided URL being aware of existing.

    :param url: string of target URL
    :param params: dict containing requested params to be added
    :return: string with updated URL
    
    >> url = 'https://stackoverflow.com/test?answers=true'
    >> new_params = {'answers': False, 'data': ['some','values']}
    >> add_url_params(url, new_params)
    'https://stackoverflow.com/test?data=some&data=values&answers=false'
    """
    # Unquoting URL first so we don't lose existing args
    url = unquote(url)
    # Extracting url info
    parsed_url = urlparse(url)
    # Extracting URL arguments from parsed URL
    get_args = parsed_url.query
    # Converting URL arguments to dict
    parsed_get_args = dict(parse_qsl(get_args))
    # Merging URL arguments dict with new params
    parsed_get_args.update(params)

    # Bool and Dict values should be converted to json-friendly values
    # you may throw this part away if you don't like it :)
    parsed_get_args.update(
        {k: dumps(v) for k, v in parsed_get_args.items()
         if isinstance(v, (bool, dict))}
    )

    # Converting URL argument to proper query string
    encoded_get_args = urlencode(parsed_get_args, doseq=True)
    # Creating new parsed result object based on provided with new
    # URL arguments. Same thing happens inside urlparse.
    new_url = ParseResult(
        parsed_url.scheme, parsed_url.netloc, parsed_url.path,
        parsed_url.params, encoded_get_args, parsed_url.fragment
    ).geturl()

    return new_url

请注意,可能会存在一些问题,如果您发现问题,请告诉我,我们会改进

解决方案 4:

如果字符串可以包含任意数据(例如,& 符号、斜杠等字符需要进行编码),则需要使用 URL 编码。

查看urllib.urlencode:

>>> import urllib
>>> urllib.urlencode({'lang':'en','tag':'python'})
'lang=en&tag=python'

在python3中:

from urllib import parse
parse.urlencode({'lang':'en','tag':'python'})

解决方案 5:

您还可以使用 furl 模块https://github.com/gruns/furl

>>> from furl import furl
>>> print furl('http://example.com/search?q=question').add({'lang':'en','tag':'python'}).url
http://example.com/search?q=question&lang=en&tag=python

解决方案 6:

如果您正在使用请求库:

import requests
...
params = {'tag': 'python'}
requests.get(url, params=params)

解决方案 7:

根据这个答案,简单情况的一行代码(Python 3 代码):

from urllib.parse import urlparse, urlencode


url = "https://stackoverflow.com/search?q=question"
params = {'lang':'en','tag':'python'}

url += ('&' if urlparse(url).query else '?') + urlencode(params)

或者:

url += ('&', '?')[urlparse(url).query == ''] + urlencode(params)

解决方案 8:

我发现这比两个最好的答案更优雅:

from urllib.parse import urlencode, urlparse, parse_qs

def merge_url_query_params(url: str, additional_params: dict) -> str:
    url_components = urlparse(url)
    original_params = parse_qs(url_components.query)
    # Before Python 3.5 you could update original_params with 
    # additional_params, but here all the variables are immutable.
    merged_params = {**original_params, **additional_params}
    updated_query = urlencode(merged_params, doseq=True)
    # _replace() is how you can create a new NamedTuple with a changed field
    return url_components._replace(query=updated_query).geturl()

assert merge_url_query_params(
    'http://example.com/search?q=question',
    {'lang':'en','tag':'python'},
) == 'http://example.com/search?q=question&lang=en&tag=python'

我最不喜欢上述答案(尽管它们很好):

  • queryŁukasz:必须记住URL 组件中的索引

  • Sapphire64:创建更新的非常冗长的方式ParseResult

我的回应的糟糕之处在于dict使用解包进行的合并看起来很神奇,但是由于我对可变性的偏见,我更喜欢这样而不是更新已经存在的字典。

解决方案 9:

是的:使用urllib。

从文档中的示例:

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params)
>>> print f.geturl() # Prints the final URL with parameters.
>>> print f.read() # Prints the contents

解决方案 10:

python3,我想这是不言自明的

from urllib.parse import urlparse, urlencode, parse_qsl

url = 'https://www.linkedin.com/jobs/search?keywords=engineer'

parsed = urlparse(url)
current_params = dict(parse_qsl(parsed.query))
new_params = {'location': 'United States'}
merged_params = urlencode({**current_params, **new_params})
parsed = parsed._replace(query=merged_params)

print(parsed.geturl())
# https://www.linkedin.com/jobs/search?keywords=engineer&location=United+States

解决方案 11:

我喜欢 Łukasz 版本,但由于 urllib 和 urllparse 函数在这种情况下使用起来有些尴尬,所以我认为更直接的做法是这样做:

params = urllib.urlencode(params)

if urlparse.urlparse(url)[4]:
    print url + '&' + params
else:
    print url + '?' + params

解决方案 12:

使用各种urlparse函数来拆分urllib.urlencode()组合字典中现有的 URL,然后urlparse.urlunparse()将其重新组合在一起。

或者仅获取结果urllib.urlencode()并将其适当地连接到 URL。

解决方案 13:

还有另一个答案:

def addGetParameters(url, newParams):
    (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
    queryList = urlparse.parse_qsl(query, keep_blank_values=True)
    for key in newParams:
        queryList.append((key, newParams[key]))
    return urlparse.urlunparse((scheme, netloc, path, params, urllib.urlencode(queryList), fragment))

解决方案 14:

在 Python 2.5 中

import cgi
import urllib
import urlparse

def add_url_param(url, **params):
    n=3
    parts = list(urlparse.urlsplit(url))
    d = dict(cgi.parse_qsl(parts[n])) # use cgi.parse_qs for list values
    d.update(params)
    parts[n]=urllib.urlencode(d)
    return urlparse.urlunsplit(parts)

url = "http://stackoverflow.com/search?q=question"
add_url_param(url, lang='en') == "http://stackoverflow.com/search?q=question&lang=en"

解决方案 15:

以下是我实现它的方法。

import urllib

params = urllib.urlencode({'lang':'en','tag':'python'})
url = ''
if request.GET:
   url = request.url + '&' + params
else:
   url = request.url + '?' + params    

效果很好。不过,我希望能有一种更简洁的方法来实现这一点。

实现上述内容的另一种方式是将其放入方法中。

import urllib

def add_url_param(request, **params):
   new_url = ''
   _params = dict(**params)
   _params = urllib.urlencode(_params)

   if _params:
      if request.GET:
         new_url = request.url + '&' + _params
      else:
         new_url = request.url + '?' + _params
   else:
      new_url = request.url

   return new_ur

解决方案 16:

使用yarl

from yarl import URL

url = 'http://stackoverflow.com/search?q=question'
params = {'lang': 'en', 'tag': 'python'}

url_obj = URL(url).with_query(params)
new_url = str(url_obj)
print(new_url)

yarl是的依赖项aiohttp,因此如果您正在使用aiohttp,则您已经yarl安装了。)

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   4046  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2770  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   90  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   105  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   93  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用