详解Python3的urllib.parse.urlencode函数

tech2025-12-03  22

文章目录

简介用法函数原型源代码其他参考文献

简介

常用 urllib.parse.urlencode 进行 URL 的 get 请求参数拼接。

import urllib.parse url = 'http://www.baidu.com/s' query = { 'wd': 'Python3标准库', 'ie': 'UTF-8' } print(url + '?' + urllib.parse.urlencode(query)) # http://www.baidu.com/s?wd=Python3%E6%A0%87%E5%87%86%E5%BA%93&ie=UTF-8

用法

import urllib.parse query = {} # 空dict print(urllib.parse.urlencode(query)) query = {'a': 1, 'b': 2} # dict print(urllib.parse.urlencode(query)) query = (('a', 1), ('b', 2)) # 二元素的tuple序列 print(urllib.parse.urlencode(query)) query = (('a', [1, 2]), ('b', [2, 3])) # 值是序列,且doseq为True,单独转换 print(urllib.parse.urlencode(query, doseq=True)) query = {b'a': b'1', b'b': b'2'} # 字节类型 print(urllib.parse.urlencode(query)) # # a=1&b=2 # a=1&b=2 # a=1&a=2&b=2&b=3 # a=1&b=2

建议使用 dict

函数原型

def urlencode(query, doseq=False, safe='', encoding=None, errors=None, quote_via=quote_plus)

参数描述query查询参数doseq序列元素是否单独转换safe安全默认值encoding编码errors错误默认值quote_via查询参数的成份是str时,safe, encoding, errors传递给的指定函数默认为quote_plus(),加强版quote()

源代码

def quote(string, safe='/', encoding=None, errors=None): """quote('abc def') -> 'abc%20def' URL的每个部分,如路径信息、查询等,若遇到保留关键字必须用引号括起来。 RFC 2396 统一资源标识符(URI)的通用语法列出了以下保留关键字。 reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," 每个字段都保留在URL中,但不是所有字符都保留在字段中。(Each of these characters is reserved in some component of a URL, but not necessarily in all of them.) 默认情况下,quote()用于URL的path部分。因此,它不会对'/'进行编码。此字符是保留的,但在典型的用法中,quote函数会在使用现有斜杠字符作为保留字符的path部分上调用。 string和safe可以是str或bytes对象。如果字符串是字节对象,则不能指定encoding和errors。 可选的encoding和errors指定如何处理string。encode方法接受非ASCII字符。默认情况下,encoding='utf-8',errors='strict'(不支持的字符会引发UnicodeEncodeError)。 """ if isinstance(string, str): if not string: return string if encoding is None: encoding = 'utf-8' if errors is None: errors = 'strict' string = string.encode(encoding, errors) else: if encoding is not None: raise TypeError("quote() doesn't support 'encoding' for bytes") if errors is not None: raise TypeError("quote() doesn't support 'errors' for bytes") return quote_from_bytes(string, safe) def quote_plus(string, safe='', encoding=None, errors=None): """类似quote(),可以将' '替换为'+'。原始字符串中的加号将进行转义,除非它们包含在safe中。safe没有默认为'/'。 """ # 检查' '是否在字符串中,字符串可以是str或bytes。如果没有空格,常规的引用会有正确的结果。 if ((isinstance(string, str) and ' ' not in string) or (isinstance(string, bytes) and b' ' not in string)): return quote(string, safe, encoding, errors) if isinstance(safe, str): space = ' ' else: space = b' ' string = quote(string, safe + space, encoding, errors) return string.replace(' ', '+') def urlencode(query, doseq=False, safe='', encoding=None, errors=None, quote_via=quote_plus): """将一个dict或二元素的tuple编码为一个URL查询字符串。 如果query中所有值都是序列,并且doseq为True,那么每个序列元素都被转换为一个单独的参数 如果query是一个二元素的tuple序列,则输出中参数的顺序将与输入中参数的顺序匹配。 查询参数的成份可以是字符串类型,也可以是字节类型。 当查询参数的成份是str时,safe, encoding, errors传递给指定的函数quote_via。 """ if hasattr(query, "items"): # 有items属性的话(即dict)直接取出 query = query.items() else: # 查询参数为字符串或序列时 try: # 有内容但序列第一个元素不为tuple时报错 if len(query) and not isinstance(query[0], tuple): raise TypeError # 所有类型的零长度序列都将成功到这,小问题。由于最初的实现允许空dict,为保持一致性,保留这种行为 except TypeError: ty, va, tb = sys.exc_info() raise TypeError("not a valid non-string sequence " "or mapping object").with_traceback(tb) l = [] if not doseq: for k, v in query: if isinstance(k, bytes): k = quote_via(k, safe) else: k = quote_via(str(k), safe, encoding, errors) if isinstance(v, bytes): v = quote_via(v, safe) else: v = quote_via(str(v), safe, encoding, errors) l.append(k + '=' + v) else: for k, v in query: if isinstance(k, bytes): k = quote_via(k, safe) else: k = quote_via(str(k), safe, encoding, errors) if isinstance(v, bytes): v = quote_via(v, safe) l.append(k + '=' + v) elif isinstance(v, str): v = quote_via(v, safe, encoding, errors) l.append(k + '=' + v) else: try: # Is this a sufficient test for sequence-ness? x = len(v) except TypeError: # not a sequence v = quote_via(str(v), safe, encoding, errors) l.append(k + '=' + v) else: # loop over the sequence for elt in v: if isinstance(elt, bytes): elt = quote_via(elt, safe) else: elt = quote_via(str(elt), safe, encoding, errors) l.append(k + '=' + elt) return '&'.join(l)

其他

查询字符串 a=1&a=2有什么用?服务器会拿最后的值作为a的值。

import tornado.web import tornado.ioloop import tornado.httpserver from tornado.options import define, options, parse_command_line define("port", default=8888, help="运行端口", type=int) class TestHandler(tornado.web.RequestHandler): def get(self): print(self.get_argument('a')) if __name__ == "__main__": parse_command_line() print("http://localhost:{}/?a=1&a=2".format(options.port)) app = tornado.web.Application( handlers=[ (r"/", TestHandler), ], ) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()

参考文献

urllib.parse.urlencode
最新回复(0)