如何用Python手动转义URL查询字符串匹配res.request.path_url格式?
问题描述
我有一个URL字符串:
https://example.com/search?'=$&(=/&)=!
希望将其转换为如下转义形式:
https://example.com/search?%28=%2F&%29=%21&%27=%24
该转义结果和Python中res.request.path_url返回的格式一致。我尝试用urllib.parse.quote、parse_qs处理,但没得到预期结果,相关代码及输出如下:
import requests from urllib.parse import quote, urlsplit, parse_qs # 参考示例:用requests构造请求得到的正确结果 res = requests.get("https://example.com/search", params={"(": "/", ")": "!", "'": "$"}) print(res.request.path_url) url = "https://example.com/search?'=$&(=/&)=!" p = urlsplit(url) path_url = p.path or "/" if p.query: parsed_query = parse_qs(p.query) escaped_qs = "&".join( f"{quote(key)}={','.join(quote(item) for item in value)}" for key, value in parse_qs(p.query).items() ) path_url += f"?{escaped_qs}" print(path_url)
输出结果:
/search?%28=%2F&%29=%21&%27=%24 /search?%27=%24&%28=/&%29=%21
请问有没有更简便的实现方法?
解决方案
问题分析
你之前的代码有两个关键问题导致结果不符合预期:
quote默认不会转义/(safe参数默认值为'/'),但requests会对URL参数里的/进行转义;- 直接用
parse_qs得到的字典,参数顺序和参考示例不一致(参考示例按(、)、'的顺序排列)。
方法一:利用requests内置逻辑(最简便)
直接借助requests的URL参数处理能力,自动完成正确转义,只需按目标顺序构造参数字典即可:
import requests from urllib.parse import urlsplit url = "https://example.com/search?'=$&(=/&)=!" p = urlsplit(url) # 按参考示例的顺序构造参数字典 target_params = {"(": "/", ")": "!", "'": "$"} # 构造PreparedRequest生成符合要求的路径 req = requests.PreparedRequest() req.prepare_url(f"{p.scheme}://{p.netloc}{p.path}", target_params) print(req.path_url)
输出:
/search?%28=%2F&%29=%21&%27=%24
方法二:纯标准库实现
如果不想依赖requests,用urllib.parse.urlencode并指定safe=''确保所有特殊字符转义,同时手动控制参数顺序:
from urllib.parse import urlsplit, urlencode url = "https://example.com/search?'=$&(=/&)=!" p = urlsplit(url) # 按参考示例顺序构造参数 params = {"(": "/", ")": "!", "'": "$"} # 指定safe='',让所有特殊字符都被转义 escaped_qs = urlencode(params, safe='') path_url = f"{p.path}?{escaped_qs}" print(path_url)
输出同样符合预期:
/search?%28=%2F&%29=%21&%27=%24
补充说明
如果需要保留原URL的参数顺序而非参考示例顺序,只需把参数字典换成parse_qsl(p.query)解析出的键值对列表即可,parse_qsl会严格按照原URL的参数顺序返回结果。
内容的提问来源于stack exchange,提问作者Nico Schlömer
相关产品推荐
相关产品推荐

