当前位置:  开发笔记 > 编程语言 > 正文

在Python中将params添加到给定的URL

如何解决《在Python中将params添加到给定的URL》经验,为你挑选了9个好方法。

假设我获得了一个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> Łukasz..:

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

ParseResult,结果urlparse(),是只读的,我们需要把它转换成list之前,我们可以尝试修改其数据.


您可能希望使用`urlparse.parse_qs`而不是`parse_qsl`.后者返回一个列表,而你想要一个字典.请参阅http://docs.python.org/library/urlparse.html#urlparse.parse_qs.
@florian:至少在python 2.7中,你需要将`urlencode`称为`urllib.urlencode(query,doseq = True)`.否则,原始网址中存在的参数不会被正确保留(因为它们是从@ parse_qs @中作为元组返回的
`urlparse()`和`urlsplit()`的结果实际上是`namedtuple`实例.因此,您可以将它们直接分配给变量,并使用`url_parts = url_parts._replace(query = ...)`来更新它.
我已经重写了这个以在Python 3中工作.[代码在这里](https://gist.github.com/rokcarl/20b5bf8dd9b1998880b7).
注意 - 此实现删除了某些RESTful服务使用的重复查询参数.稍加修改就可以解决这个问题.query = urlparse.parse_qsl(url_parts [4])query + = params.items()但是如果你想用dict替换现有的查询参数,需要多一点.

2> Sapphire64..:

为什么

我对这个页面上的所有解决方案都不满意(来吧,我们最喜欢的复制粘贴的东西在哪里?)所以我根据这里的答案编写了自己的解决方案.它试图完成并且更加Pythonic.我在参数中为dictbool值添加了一个处理程序,以便更加消费者(JS)友好,但它们是可选的,你可以放弃它们.

这个怎么运作

测试1:添加新参数,处理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'

测试2:重写现有的args,处理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

请注意,可能存在一些问题,如果你找到一个请告诉我,我们会更好地做这件事



3> Mike Mueller..:

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

查看urllib.urlencode:

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



4> surfeurX..:

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



5> Varun..:

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

这就是我要做的:

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)



6> unwind..:

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


-1用于使用HTTP请求来解析URL(实际上是基本的字符串操作).此外,不考虑实际问题,因为您需要知道URL如何能够正确附加查询字符串.

7> Mikhail Gera..:

根据这个答案,简单案例的单线程(Python 3代码):

from urllib.parse import urlparse, urlencode


url = "/sf/ask/17360801/?q=question"
params = {'lang':'en','tag':'python'}

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

要么:

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


我知道你提到了"简单案例",但要澄清一下:如果锚中有一个`?`(`#?stuff`),它将无法正常工作.

8> Christophe R..:

如果您正在使用请求lib:

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



9> Facundo Olan..:

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

params = urllib.urlencode(params)

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


怎么样.query而不是[4]?
推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有