在Python中将参数添加到给定的URL

假设我被给了一个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

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

urlliburlparse模块有一些怪癖。 这是一个工作的例子:

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

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

如果string可以具有任意数据(例如,诸如和符,斜杠等字符将需要编码),则要使用URL编码。

查看urllib.urlencode:

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

为什么

我一直不满意这个页面上的所有解决scheme( 来吧,我们最喜欢的复制粘贴的东西在哪里? ),所以我根据这里的答案写了我自己的。 它试图完成,更Pythonic。 我已经在参数中为dictbool值添加了一个处理程序,使其更具用户端( JS )友好性,但它们仍然是可选的,您可以放弃它们。

怎么运行的

testing1:添加新的参数,处理Arrays和Bool值:

 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' 

testing2:重写现有的参数,处理DICT值:

 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: # 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 = 'http://stackoverflow.com/test?answers=true' >> new_params = {'answers': False, 'data': ['some','values']} >> add_url_params(url, new_params) 'http://stackoverflow.com/test?data=some&data=values&answers=false' """ # Unquoting URL first so we don't loose 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 of 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 

请注意,可能有一些问题,如果你find一个,请让我知道,我们会做得更好

您也可以使用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 

是的:使用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 

基于这个答案,对于简单的情况(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) 

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

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

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

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

还有一个答案:

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

在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" 

这是我如何实现它。

 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 

如果您正在使用请求lib:

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