Python中的urlencode和urldecode


=Start=

缘由:

在用Python发起网络请求的时候,有一些场景会需要对传入的参数进行URL编码后再进行请求,在这里记录一下用Python进行URL编解码的方法和在实际使用过程中碰到和解决的问题,方便以后参考。

正文:

参考解答:
方法1(针对字符、字符串的URL编解码):

URL编码:urllib.quote()函数(在处理空格的时候,urllib.quote()会将空格替换成「%20」,而urllib.quote_plus()会将空格替换成「+」号)

In [1]: import urllib

In [3]: urllib.quote('http://ixyzero.com/blog/hi world')
Out[3]: 'http%3A//ixyzero.com/blog/hi%20world'

In [4]: urllib.quote_plus('http://ixyzero.com/blog/hi world')
Out[4]: 'http%3A%2F%2Fixyzero.com%2Fblog%2Fhi+world'

URL解码:urllib.unquote()函数(对应的还有一个urllib.unquote_plus()函数,会将字符串中的「+」替换成空格)

>>> from urllib import unquote
>>> unquote('http%3A//www.baidu.com')
'http://www.baidu.com'
方法2(针对dict格式的数据的URL编码):

URL编码:urllib.urlencode()函数,但这个函数只能接收「键-值」格式的数据。即只针对dict的,并且目前不提供urldecode方法:

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> params #自动转化成下面url的参数形式
'eggs=2&bacon=0&spam=1'
>>> f = urllib.urlopen("http://ixyzero.com/cgi-bin/query?%s" % params)
>>> print f.read()
方法2的扩展:

对于同名的URL参数,urllib.urlencode只会返回对最后一个的编码值:

data = urllib.urlencode({ 'tag': 'corp=abc&owt=test&pdl=m', })
# tag=corp%3Dabc%26owt%3Dtest%26pdl%3Dm

data2 = urllib.urlencode({ 'tag': 'corp=abc&owt=test&pdl=m', 'tag': 'corp=abc&owt=ops', })
# tag=corp%3Dabc%26owt%3Dops

target_url = 'http://ixyzero.com/api/tag/admin?tag=corp%3Dabc%26owt%3Dtest%26pdl%3Dm&tag=corp%3Dabc%26owt%3Dops'
print urllib.unquote(target_url)

所以如果希望能在URL中放多个同名的参数,有两个方法:

方法一:在for循环中进行urllib.urlencode调用,最后拼接

比如:

host_tag_dict = {'hostname1':'corp=abc&owt=test&pdl=m', 'hostname2':'corp=abc&owt=ops', }
base_url = 'http://ixyzero.com/api/tag/admin?'
encode_tags = []
for host in host_tag_dict:
    if host_tag_dict[host]:
        encode_tags.append(urllib.urlencode({'tag': host_tag_dict[host]}))
tag_admin_url = '{0}{1}'.format(base_url, '&'.join(encode_tags))
print(tag_admin_url)

方法二:在requests中的params参数里面设置key的值为一个list

比如:

payload = {'tag': ['corp=abc&owt=test&pdl=m', 'corp=abc&owt=ops'], }
r = requests.get('http://ixyzero.com/api/tag/admin?', params=payload)    #会产生实际请求,不便于本地测试
print(r.url)
参考链接:

=END=


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注