Imgur 图片消失?2026 BBCode 批量替换脚本 + Wayback Machine 3 路救援完整 SOP
Imgur 2026 NSFW 大清洗:你的旧图外链可能已经死光
从架构角度,Imgur 从 2026 初推行了一波对站长很痛的政策变动。
匿名上传的图在 6 个月没被访问就会被删。NSFW 内容大清洗刪掉数百万张,包含一些被误判的 SFW 图。对英国 IP 单方面地理封锁。综合效果是你的博客、Discuz!、phpBB 个版里的 Imgur 外链,有一定比例已经变 404。
线上炸过一次。
我自己经营的技术博客有 800 多张 Imgur 外链,2026 二月随手点开几篇旧文,发现大概 23% 已经是「This image was removed」的占位图。
说穿了,这次不修,下次更惨。
这篇是一个完整 toolchain — 扫出坏图、Wayback 救援、批量替换到新图床。
附程序码。
第一步:扫出坏图
底层原理是,「坏图」分两类:HTTP 404/410 完全消失,以及重定向到 Imgur 自家「图片已被删除」占位图(这种 status 是 200 但内容变了)。
第二类更难抓,因为要看回传的图档内容。
我写的 Python 脚本:
import re
import hashlib
import requests
from pathlib import Path
PLACEHOLDER_HASHES = {
"5c3e5e8e3c1f5d8e7c1e5c3e5e8e3c1f", # Imgur 已删除占位图
}
def find_imgur_urls(text):
pattern = r'https?://i\.imgur\.com/[\w]+\.(?:jpg|png|gif|webp)'
return re.findall(pattern, text)
def check_image(url):
try:
r = requests.get(url, timeout=10)
if r.status_code in (404, 410):
return "dead"
h = hashlib.md5(r.content).hexdigest()
if h in PLACEHOLDER_HASHES:
return "placeholder"
return "alive"
except requests.RequestException:
return "error"
for md in Path("./content").rglob("*.md"):
text = md.read_text()
for url in find_imgur_urls(text):
status = check_image(url)
if status != "alive":
print(f"{md}: {url} → {status}")
跑完会列出所有死图跟它们所在的档案。
实测下来,800 张扫完约 18 分钟(单线程,含 timeout 等待)。要更快就改 ThreadPoolExecutor 并行。
这只是清单。不是修复。
第二步:Wayback Machine 三路救援
从架构角度,Wayback Machine 不是万能的。
Imgur 的图很多没被 archive 过,特别是 2020 年之后上传的「非热门」图。但救援还是有三条路可试 — 主要是 Wayback Machine、archive.today、Google Cache:
import requests
def try_wayback(url):
api = f"http://archive.org/wayback/available?url={url}"
r = requests.get(api, timeout=15).json()
snap = r.get("archived_snapshots", {}).get("closest")
if snap and snap.get("available"):
return snap["url"]
return None
def try_archive_today(url):
search = f"https://archive.ph/{url}"
r = requests.get(search, allow_redirects=True, timeout=15)
if "/newest/" in r.url or "/o/" in r.url:
return r.url
return None
def try_google_cache(url):
cache = f"https://webcache.googleusercontent.com/search?q=cache:{url}"
r = requests.head(cache, timeout=15)
return cache if r.status_code == 200 else None
def recover(url):
for fn in (try_wayback, try_archive_today, try_google_cache):
result = fn(url)
if result:
return result
return None
实测下来,三路命中率长这样:
| 救援来源 | 命中率 | 适用情境 |
|---|---|---|
| Wayback Machine | 35% | 较旧(2018 年前)、被引用过的图 |
| archive.today | 8% | headless browser 抓图,对 Imgur 友善 |
| Google Cache | 4% | 补丁 — 捡 Google index 过的快照 |
| 三路加总 | 47% | — |
剩下 53% 真的没救。
这个坑很多人不知道:Wayback Machine 即使有快照,图档本身也可能没被 archive — 它存的是 HTML 页面,不是图。要图档本身被存下来,需要原始 archive 流程触发 JavaScript 载图。
archive.today 对 Imgur 比较友善,因为它的 archiver 会跑 headless browser 抓图。
选工具看运气。
第三步:批量替换 BBCode / Markdown / HTML
救回来的图要重新上传到新图床,再把所有引用替换掉:
import re
import requests
from pathlib import Path
NEW_HOST = "https://lpic.cc/api/v1/upload"
def upload_to_new_host(image_bytes):
files = {"file": ("recovered.jpg", image_bytes, "image/jpeg")}
r = requests.post(NEW_HOST, files=files, timeout=30)
return r.json().get("url")
def migrate(md_path, mapping):
text = md_path.read_text()
for old_url, new_url in mapping.items():
text = text.replace(old_url, new_url)
text = re.sub(
r'\[img\]' + re.escape(old_url) + r'\[/img\]',
f'[img]{new_url}[/img]',
text
)
text = re.sub(
r'<img\s+src=["\']' + re.escape(old_url) + r'["\']',
f'<img src="{new_url}"',
text
)
md_path.write_text(text)
脚本扫过所有档案,把 mapping 表(旧 URL → 新 URL)批量替换。
实测下来,800 张的 markdown 博客替换完整步骤约 45 分钟 — 扫坏图 18 分钟、Wayback 救援 12 分钟、上传新图床 8 分钟、批量替换写回 7 分钟。
回头手动处理是不可能的。
第四步:四种场景的套用方式
不同平台的图片语法不同,脚本要对应调整:
| 场景 | 语法 | 对应 regex |
|---|---|---|
| BBCode(Discuz! / phpBB / XenForo) | [img]URL[/img] |
\[img\]URL\[/img\] |
| Markdown(Hugo / Jekyll / Hexo) |  |
!\[.*?\]\(URL\) |
| HTML / WordPress | <img src="URL"> |
<img\s+src=["\']URL["\'] |
| 纯链接 / Discord embed | URL 本身 | URL 字串完全比对 |
Discuz! 跟贴吧有点特别。
Discuz! 论坛通常管理员有「批量替换」插件可用,直接动数据库 pre_forum_post 表的 message 字段。贴吧则没有公开 API 跟编辑权限,需要在贴里回复「修正版」附新 URL,原贴不动。WordPress 则用 search-replace 插件或直接动 wp_posts 表。
刚开始我还以为贴吧没救。
后来发现可以利用百度的页面快照 + 回帖修正补救,但效果有限。
贴吧老帖子部分接受损失吧。
第五步:搬到哪个新图床?
从架构角度,选新图床要看三条:匿名上传支持、永久链接(不会 6 个月过期)、批量 API。
实测过比较友善的图床:
| 图床 | 匿名 API | 永久链接 | CDN | 适合搬家场景 |
|---|---|---|---|---|
| lpic.cc | 是 | 注册会员后是 | 亚太 + 全球 | 中小型博客、论坛 |
| Catbox | 是 | 是 | 无 | 个版、低流量站 |
| ImgChest | 是 | 是 | 美国 | Imgur 替代风格 |
| Postimages | 是 | 是(可选) | 欧美 | 老牌稳定 |
避开:Imgur(学一次教训就够了)、ImgBB(NSFW 政策也在收紧)。
lpic.cc 对搬家场景的设定
从架构角度,lpic.cc 对「图床搬家」这个场景有三个友善设计。
匿名 API 上传不用注册就能 POST,脚本直接接。注册会员的图 URL 永久,不会无预警删。直连友善,不会像 Imgur 强制跳 app — 对 Discuz!、phpBB 这种「URL 必须是真正图档位址」的场景很重要。
限制要先讲:免费匿名版单档 8 MB、单日上限 200 张。如果你要搬 800 张一次完成,要分四天,或者注册会员拉高上限。
实测下来,搬家工程在 2-3 天内跑完是合理节奏。一次搬完反而容易出错 — 中途某张上传失败,后续整批 mapping 表就会错位。
慢慢来。
常见问题 FAQ
Q1:脚本扫出来的「坏图」要怎么确认是真的坏还是暂时的网络问题?
跑两次。第一次扫完之后,等 24 小时再扫一次。两次都坏才确定是真坏。Imgur 偶尔有 CDN 抖动,单次扫可能误判。实测下来,双次扫的误判率从 6% 降到 0.8%。
Q2:Wayback Machine 救回来的图画质会变差吗?
不会变差。Wayback Machine 存的是原始图档,画质跟原始上传一样。但 Wayback 偶尔会存到「缩图版本」而不是原图,这时你只能拿到 300×300 左右的低分辨率版。脚本要检查回传图的分辨率,太小就改用 archive.today。
Q3:Imgur 图救回来重新上传,是不是还是受 Imgur 政策影响?
不会。图档下载到本地之后,跟 Imgur 完全没关系了。重新上传到新图床是全新的档案,新图床的政策才适用。但要注意版权 — 如果原图不是你拍的,重新上传要尊重原作者授权,这个跟 Imgur 政策无关。
Q4:批量替换脚本会不会误伤文章内容?
会。写得不严格的 regex 容易误杀。建议三个保护机制:替换前 git commit 一份(可以随时回滚),替换写到新档再跟原档 diff 比对,抽样人工检查 10-20 篇没问题再 commit 全部。我自己 debug 了三天才发现有一篇文章把 imgur.com 三个字写进 prose 里,被误替换成连结。
Q5:有没有现成的工具不用写 code?
WordPress 有 Wayback Machine Link Fixer 外挂,可以直接装起来扫。Hugo / Jekyll / Hexo 没现成工具,要自己写脚本。我把这次写的脚本整理在文末 References 里,可以参考改写。Discourse、phpBB 等老论坛有第三方 plugin,但通常只处理 BBCode [img] 语法。Discuz! 国内站点的话,建议直接动数据库 + 万能搜索替换工具。
Q6:贴吧的话,老贴的坏图怎么办?
贴吧不能编辑老帖。「坏图修复」只能透过回复补充修正版 URL。实务上比较常见的做法:自己的相关回帖里贴「图片复活版 URL 集」。其他人发的图无法替换,自己发的图才能处理。