直接用re提取+base64.b64decode()易崩,核心问题在提取不全、校验缺失、MIME误判;需用不区分大小写正则匹配HTML/CSS多位置Base64字符串,清理空白、补padding、处理URL-safe变体,并依MIME推导扩展名、哈希生成文件名,批量时限流防OOM。

直接用 re 提取 + base64.b64decode() 解码就能跑通,但线上环境一抓就崩——核心问题不在解码本身,而在提取不全、校验缺失、MIME误判这三处。
怎么从 HTML 和 CSS 里完整抓出 Base64 图片字符串
Base64 图片不止在 里,还藏在 style 属性、 的 href、甚至内联 <script></script> 中的字符串拼接里。只扫 img[src] 会漏掉一半以上。
- 用不区分大小写的正则:
r'data:image/([^;]+);base64,([^"\'>\s]+)',注意匹配到分号后、引号/空格/尖括号前的连续非空白字符 - CSS 里的
background-image: url("data:image/png;base64,...")需先提取所有style内容或外部 CSS 文本,再对整段文本跑正则 - 别用
BeautifulSoup.find_all('img', src=re.compile(...))—— 它不支持跨标签内容匹配,也抓不到 JS 动态插入的样式 - 静态页够用;若页面靠 JS 渲染图片(比如懒加载、SPA),必须换
Playwright或Selenium获取渲染后 HTML
为什么 base64.b64decode() 常报 binascii.Error
不是所有带 base64, 的字符串都符合标准:可能含换行、空格、URL-safe 字符(-、_),或 padding 缺失。直接传给 b64decode 必然炸。
- 先清理:用
re.sub(r'[\s\n\r]+', '', b64_str)去掉所有空白符 - 补 padding:长度对 4 取余,缺几位就补几个
'=',b64_str += '=' * (4 - len(b64_str) % 4) - 如果是 URL-safe 变体(含
-/_),先替换为标准字符:b64_str.replace('-', '+').replace('_', '/') - 务必包
try/except binascii.Error,跳过单条失败项,别让整个批量任务中断
保存文件时如何正确推导扩展名和文件名
硬写 .png 或靠文件头 magic bytes 判定,都会在某些站点翻车。真实场景中,MIME 类型才是唯一可靠依据,而文件名重复会导致覆盖。
- MIME 类型来自正则第一组:
image/jpeg→.jpg,image/webp→.webp,image/svg+xml→.svg - 别用原始字符串做文件名:含斜杠、空格、不可见字符,容易 OSError;建议用
hashlib.md5(b64_str.encode()).hexdigest()[:12]生成前缀 - 批量处理时加限流:每秒最多解码 5–10 条,避免内存暴涨;大图(>2MB Base64 字符串)可先跳过或单独走流式解码
最常被忽略的是:同一个页面里可能混着标准 Base64、URL-safe Base64、甚至自定义字符表的变体(比如某银行门户用 RSTUV...= 替代标准字母表)。没做预检测就统一 decode,结果是大量“解出来是乱码”的假成功。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











