Python的单层与双重URL解码实战与踩坑指南

 更新时间:2026年09月30日 08:39:36   作者:detayun  
在爬虫、接口对接工作中,URL编码与解码是绕不开的基础操作,相比于编码,解码更容易踩坑,尤其是双重URL编码,因此本文使用Python内置urllib.parse,不需要任何第三方库,带你彻底搞懂URL解码,需要的朋友可以参考下

前言

在爬虫、接口对接工作中,URL编码与解码是绕不开的基础操作。相比于编码,解码更容易踩坑,尤其是双重URL编码,很多人看到一串满是%25的字符串,直接一次unquote就结束,最后拿到的还是编码后的JSON字符串,接口解析直接报错。本文使用Python内置urllib.parse,不需要任何第三方库,带你彻底搞懂URL解码。

一、URL解码基础概念

URL编码是把特殊字符转成%加十六进制;URL解码就是反向操作,把%XX还原为原始字符。

常见编码映射对照(解码时就是反向转换)

  • %22 → "
  • %7B → {
  • %7D → }
  • %3A → :
  • %2C → ,
  • %25 → % 这是双重编码最关键的字符

Python内置模块urllib.parse.unquote负责URL解码。

配套还有unquote_plus,和unquote有区别:unquote_plus会把+还原成空格,适用于form表单的查询串;普通URL路径、参数解析优先使用unquote。

单层解码基础示例:

from urllib.parse import unquote

# 单层编码后的字符串
encoded_str = "%7B%22articleId%22%3A%2289c46c77f90e61ff7df01e3cc18eae9349f619f697ca4366e94fad724d913ee6%22%2C%22columnId%22%3A%22268f86fdf61ac8614f09db38a2d0295253043b03e092c7ff48ab94290296125c%22%7D"

raw = unquote(encoded_str)
print(raw)
# 输出:{"articleId":"89c46c77f90e61ff7df01e3cc18eae9349f619f697ca4366e94fad724d913ee6","columnId":"268f86fdf61ac8614f09db38a2d0295253043b03e092c7ff48ab94290296125c"}

二、双重URL解码(爬虫高频场景)

当字符串里面大量出现%25,说明是双重URL编码。
原理回顾:

  1. 原始JSON:{"articleId":"xxx"}
  2. 第一次quote → %7Bxxx%7D
  3. 第二次quote,把%编码成%25 → %257B%2522articleId%2522...

解码顺序必须反过来:先unquote一次,再unquote第二次。只解码一次,拿到的还是第一层编码后的字符串,无法直接json.loads。

实战案例

我们拿到接口参数:
params=%257B%2522articleId%2522%3A%252289c46c77f90e61ff7df01e3cc18eae9349f619f697ca4366e94fad724d913ee6%2522%2C%2522columnId%2522%3A%2522268f86fdf61ac8614f09db38a2d0295253043b03e092c7ff48ab94290296125c%2522%257D

完整解码代码:

from urllib.parse import unquote
import json

full_param = "params=%257B%2522articleId%2522%3A%252289c46c77f90e61ff7df01e3cc18eae9349f619f697ca4366e94fad724d913ee6%2522%2C%2522columnId%2522%3A%2522268f86fdf61ac8614f09db38a2d0295253043b03e092c7ff48ab94290296125c%2522%257D"

# 截取 params= 后面的值
encode_value = full_param.split("params=")[1]

# 双重解码
decode_step1 = unquote(encode_value)
decode_step2 = unquote(decode_step1)

# 转为字典
data = json.loads(decode_step2)
print(data)

执行过程拆解:

  1. 第一次unquote:%257B → %7B,得到单层编码串
  2. 第二次unquote:%7B → {,得到原始JSON字符串
  3. json.loads 加载成Python字典

三、直接解析完整URL中的查询参数

日常开发,我们经常拿到完整URL,需要直接解析query参数,parse_qs内部自带解码,不用手动unquote。

from urllib.parse import urlparse, parse_qs

url = '[https://www.chinaisa.org.cn/gxportal/xfgl/portal/content.html?articleId=89c46c77f90e61ff7df01e3cc18eae9349f619f697ca4366e94fad724d913ee6&columnId=268f86fdf61ac8614f09db38a2d0295253043b03e092c7ff48ab94290296125c](https://www.chinaisa.org.cn/gxportal/xfgl/portal/content.html?articleId=89c46c77f90e61ff7df01e3cc18eae9349f619f697ca4366e94fad724d913ee6&columnId=268f86fdf61ac8614f09db38a2d0295253043b03e092c7ff48ab94290296125c)'
parsed = urlparse(url)
query = parse_qs(parsed.query)
# parse_qs 返回value是列表
res = {k:v[0] for k, v in query.items()}
print(res)

注意:parse_qs 会自动做URL解码,不要再次手动unquote,否则会重复解码引发bug。

四、unquote 和 unquote_plus 的区别(重点踩坑点)

  • unquote:标准URL解码,空格还原成%20 → 空格。适合URL路径、参数。
  • unquote_plus:表单application/x-www-form-urlencoded专用,+会被转成空格。

示例对比:

from urllib.parse import unquote, unquote_plus

s = "hello%20world+test"
print(unquote(s))      # hello world+test
print(unquote_plus(s)) # hello world test

错误混用会导致+号被误转空格,参数直接错乱。

五、常见解码踩坑清单

坑1:双重编码只解码一次

现象:解码后的字符串还包含大量%,json.loads直接抛出JSONDecodeError。
判断依据:字符串包含%25,几乎就是双重编码,需要两次unquote。

坑2:对 parse_qs 的结果再次unquote

parse_qs内部已经自动完成解码,再次unquote会二次解码,遇到%25这类字符会产生脏数据。

坑3:中文解码编码不匹配

unquote默认encoding='utf-8',如果是GBK编码的老网站,会抛出UnicodeDecodeError。
解决方案:指定编码 unquote(s, encoding="gbk")

# GBK编码解码示例
from urllib.parse import unquote
s = "%D6%D0%CE%C4"
print(unquote(s, encoding="gbk"))

坑4:不合法的%编码串

原始字符串截断,出现%3这种不完整的编码,默认会抛异常。可以设置errors='replace'忽略错误。

unquote(s, errors='replace')

六、封装通用函数:自动处理单层/双重解码

写一个简易工具函数,判断是否包含%25,自动选择解码次数,方便项目直接复用:

from urllib.parse import unquote
import json

def auto_double_decode(s: str):
    """自动判断单层/双重URL解码,返回原始字符串"""
    if "%25" in s:
        s = unquote(unquote(s))
    else:
        s = unquote(s)
    return s

# 测试
encoded = "%257B%2522articleId%2522%3A%252289c46c77f90e61ff7df01e3cc18eae9349f619f697ca4366e94fad724d913ee6%2522%2C%2522columnId%2522%3A%2522268f86fdf61ac8614f09db38a2d0295253043b03e092c7ff48ab94290296125c%2522%257D"
raw_json = auto_double_decode(encoded)
data = json.loads(raw_json)
print(data)

提示:这个简易函数仅适用于爬虫常见场景,极端多层编码(3层及以上)不适用。

七、什么时候会遇到双重编码需要解码

  1. 老Java政务、国企网站,网关、Nginx多层转发,每层自动解码
  2. 前端JS编码后,浏览器发起请求再次自动编码
  3. 接口返回的参数是经过两层编码的JSON字符串,放在URL query里面传递

八、小结

URL解码核心是urllib.parse.unquote,单层解码是基础;%25是识别双重URL编码最直观的标记,遇到它就要连续两次解码。

开发中还要区分unquote和unquote_plus,不要在parse_qs解析完成后重复解码。遇到中文乱码记得切换gbk编码。
编码和解码成对学习,在爬虫对接老旧门户、复杂网关转发接口时,能解决一大半参数解析失败的问题。

以上就是Python的单层与双重URL解码实战与踩坑指南的详细内容,更多关于Python单层与双重URL解码的资料请关注脚本之家其它相关文章!

相关文章

  • python利用tkinter实现图片格式转换的示例

    python利用tkinter实现图片格式转换的示例

    这篇文章主要介绍了python利用tkinter实现图片格式转换,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下
    2020-09-09
  • python对离散变量的one-hot编码方法

    python对离散变量的one-hot编码方法

    今天小编就为大家分享一篇python对离散变量的one-hot编码方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 在TensorFlow中实现矩阵维度扩展

    在TensorFlow中实现矩阵维度扩展

    这篇文章主要介绍了在TensorFlow中实现矩阵维度扩展方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • Python实现快速排序的方法详解

    Python实现快速排序的方法详解

    这篇文章主要介绍了Python实现快速排序的方法,结合实例形式详细分析了快速排序的思路、原理及Python具体实现技巧与相关操作注意事项,需要的朋友可以参考下
    2019-10-10
  • JSON Web Tokens的实现原理

    JSON Web Tokens的实现原理

    本文主要介绍了JSON Web Tokens的实现原理。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-04-04
  • Python实现线性拟合及绘图的示例代码

    Python实现线性拟合及绘图的示例代码

    在数据处理和绘图中,我们通常会遇到直线或曲线的拟合问题,本文主要介绍了Python实现线性拟合及绘图的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • Pytorch中关于model.eval()的作用及分析

    Pytorch中关于model.eval()的作用及分析

    这篇文章主要介绍了Pytorch中关于model.eval()的作用及分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • 单身狗福利?Python爬取某婚恋网征婚数据

    单身狗福利?Python爬取某婚恋网征婚数据

    今天我就当回媒婆,给男性程序员来点福利.今天目标爬取征婚网上呈现出来的女生信息保存成excel表格供大家筛选心仪的女生,需要的朋友可以参考下
    2021-06-06
  • Django csrf 验证问题的实现

    Django csrf 验证问题的实现

    csrf是通过伪装来自受信任用户的请求来利用受信任的网站。这篇文章主要介绍了Django csrf 验证问题的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • 对python pandas读取剪贴板内容的方法详解

    对python pandas读取剪贴板内容的方法详解

    今天小编就为大家分享一篇对python pandas读取剪贴板内容的方法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-01-01

最新评论