Python urllib.parse.urlencode 怎样生成重复键查询串
来源:17golang原创
时间:2026-10-27 00:18:00 151浏览 收藏
把列表作为参数值并设置 doseq=True,就能让 urlencode() 为每个元素生成一组重复键;若要直接控制参数顺序,也可以传入包含重复键的二元组列表。不要在普通字典中重复写同一个键,它无法同时保存那两条键值记录。
官方文档:https://docs.python.org/3.14/library/urllib.parse.html#urllib.parse.urlencode。最小示例:
from urllib.parse import urlencode
# tag 的每个元素单独生成一组同名参数
params = {"tag": ["blue", "large"], "page": "1"}
query = urlencode(params, doseq=True)按这份输入,query 应为 tag=blue&tag=large&page=1。下文代码只作解释,未运行、未访问接口,也未搭建筛选页面。
多选筛选先保留多个值
假设商品筛选允许用户同时选择“蓝色”和“大号”。界面里出现两个选中项,后端协议约定用多个同名 tag 参数表达它们。这时查询串里的重复键不是冗余,而是多选状态的表示方式。
先在程序中保留列表或键值对,不要把多个值提前拼成逗号字符串。tag=blue,large 是一个值,tag=blue&tag=large 才是两个同名参数;服务端是否把它们理解成多个筛选条件,需要双方接口协议一致。
如果用普通字典先后给 tag 赋两次字符串,旧值会被替换。等数据结构已经丢失第一项,再使用任何编码参数都无法将它恢复。

用 doseq 或二元组列表表达重复键
第一种形式把多选状态保存为列表,由 doseq 展开。第二种形式把每个键值对直接写出来:
from urllib.parse import urlencode
# 二元组列表直接保留重复键及参数排列
pairs = [("tag", "blue"), ("tag", "large"), ("page", "1")]
query = urlencode(pairs)这个列表中两条 tag 记录都存在。由于每个值已经是单个字符串,不需要为了重复键再开启 doseq。二元组列表编码后的参数排列与列表中的排列一致。
doseq 的职责是展开作为值的序列,并不是扫描一个已经生成的查询串,也不会给参数名自动加方括号。如果接口要求 tag[],应把它作为真实键名传入;这与协议采用重复 tag 是不同约定。
不设置 doseq 却把列表直接作为值传入时,不能期待它自动得到多个参数。选择哪一种数据形状,应从筛选状态的原始结构出发,避免生成前反复转换。
把筛选状态集中到一个生成函数
多处页面都要生成筛选链接时,可以集中规定空值、页码和字符串编码。下面的函数只负责返回查询部分,不拼完整地址,也不发送请求。
from urllib.parse import urlencode
def build_filter_query(tags, keyword="", page=1):
# 示例限制:调用者提供字符串标签列表、字符串关键词和正整数页码
if not isinstance(tags, list) or any(not isinstance(tag, str) for tag in tags):
raise TypeError("tags 必须是字符串列表")
if not isinstance(keyword, str):
raise TypeError("keyword 必须是字符串")
if isinstance(page, bool) or not isinstance(page, int) or page 这里把 page 转成字符串,再交给编码器;业务类型和有效范围先由生成函数处理。标签顺序沿用调用方列表,不使用集合,因此不会额外改变用户选择的排列,也不会擅自去重。
该函数约定空标签不发送,空关键词不发送,page 总是发送。这是示例自己选择的接口规则,不是所有服务端都应使用的通用答案。如果后端把空值当成一种筛选含义,应调整约定。

让可读状态与编码结果各司其职
生成出的百分号编码适合传输,不适合直接充当选项说明。界面仍应显示“蓝色”“大号”等用户能理解的名称,保留选中状态,并在移除某个选项后按最新状态重新生成参数。这样不会把维护编码字符串的责任交给用户。
键名最好使用接口约定的稳定标识,显示文案可以独立调整。不要因为编码字符串里出现加号,就把它显示成用户原本输入的加号:默认 quote_plus 会把空格编码为 +,原始加号则被转义为 %2B。
相同键可以出现多次,但服务端框架如何读取它们可能不同:有的接口取全部值,有的只取其中一项。Python 端成功生成字符串,并不能证明服务端已经采用多值语义。应在接口设计中明确重复键的处理规则。
处理空值、顺序和重复编码
| 输入或选择 | 需要明确的结果 |
|---|---|
| 列表配 doseq=True | 每个元素形成一个同名参数 |
| 含重复键的二元组列表 | 保留每条记录与参数排列 |
| 值是空字符串 | 可以表达 key=,不等于省略键 |
| 值是空列表并展开 | 没有可展开元素,不产生该键的参数对 |
| 中文、空格、加号和与号 | 传原始值,由编码器处理,避免手工拼接 |
Python 3.14 文档还标记了部分假值对象作为参数值的弃用行为。对于 page=0、空列表等情况,不要依赖隐式转换;在业务层明确省略、转成协议字符串或拒绝输入。上面的函数用字符串页码和展开后的参数对避免这种含糊。
from urllib.parse import parse_qs, parse_qsl, urlencode
# 空字符串是“明确空值”;它与不发送这个键不同
query = urlencode([("tag", ""), ("tag", "blue")])
grouped = parse_qs(query, keep_blank_values=True)
ordered_pairs = parse_qsl(query, keep_blank_values=True)
# grouped 用于按键取多个值;ordered_pairs 用于保留整体参数次序
# 这些变量是解释性示例,本文未执行也未发送网络请求parse_qs 适合按键得到值列表;parse_qsl 适合得到有序键值对。保留空字符串时要显式设置 keep_blank_values。它们可用于项目自己的往返检查,但本文没有执行检查,更没有把推导结果称为真实接口响应。
长度和处理开销取决于参数数量与文本长度。筛选项很多时,应根据接口与页面需求约束数量和长度;不要假设 URL 在所有浏览器、服务器和中间组件中都有同一个无限上限。本文不声称任何性能测试结果。
doseq=True 会把一个字符串拆成字符吗?
字符串按单个值编码,不需要为普通关键词关闭 doseq;列表值才用于表达一组值。
已经 quote 过的值还能传入吗?
通常应传原始值。把已编码百分号再次交给 urlencode,可能把百分号本身编码,导致重复编码。
重复键会自动去重吗?
不会替你做业务去重。是否保留重复选择,应在进入编码器前按接口规则决定。
依据:Python urllib.parse 官方文档,包括 urlencode、quote_plus、parse_qs 和 parse_qsl 的参数说明。
-
434 收藏
-
271 收藏
-
429 收藏
-
130 收藏
-
259 收藏
-
291 收藏
-
432 收藏
-
188 收藏
-
156 收藏
-
359 收藏
-
文章 · python教程 | 1小时前 | python · logging · Python logging.handlers.MemoryHandler 日志缓冲 批量刷新 flushLevel181 收藏
-
262 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习