为什么
我一直不满意本页面上的所有解决方案(来吧,我们最喜欢的复制粘贴在哪里?),因此我根据这里的答案编写了自己的代码。它试图是完整和更符合Python习惯。我添加了一个处理程序来处理参数中的dict和bool值以更有利于消费者端(JS)友好,但它们是可选的,你可以舍弃它们。
它是如何工作的
测试1: 添加新的参数,处理数组和布尔值:
url = 'http://stackoverflow.com/test'
new_params = {'answers': False, 'data': ['some','values']}
add_url_params(url, new_params) == \
'http://stackoverflow.com/test?data=some&data=values&answers=false'
测试2:重写现有参数,处理字典值:
url = 'http://stackoverflow.com/test/?question=false'
new_params = {'question': {'__X__':'__Y__'}}
add_url_params(url, new_params) == \
'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:
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'
"""
url = unquote(url)
parsed_url = urlparse(url)
get_args = parsed_url.query
parsed_get_args = dict(parse_qsl(get_args))
parsed_get_args.update(params)
parsed_get_args.update(
{k: dumps(v) for k, v in parsed_get_args.items()
if isinstance(v, (bool, dict))}
)
encoded_get_args = urlencode(parsed_get_args, doseq=True)
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
请注意可能会出现一些问题,如果您发现了,请告诉我,我们将使这件事变得更好
urlparse.parse_qs
而不是parse_qsl
。后者返回一个列表,而你想要一个字典。请参见http://docs.python.org/library/urlparse.html#urlparse.parse_qs。 - Florian Bruckerurlencode
作为urllib.urlencode(query, doseq=True)
调用。否则,原始URL中存在的参数将无法正确保留(因为它们会被parse_qs
返回为元组)。 - rlubaurlparse()
和urlsplit()
的结果实际上是namedtuple
实例。因此,您可以直接将它们分配给一个变量,并使用url_parts = url_parts._replace(query = …)
对其进行更新。 - Feuermurmel