返回部落格
教學指南技術科普

Imgur 圖片消失?2026 BBCode 批次替換腳本 + Wayback 3 路救援完整 SOP

發佈於11 min read
分享文章

Imgur 2026 NSFW 大清洗:你的舊圖外連可能已經死光

從架構角度,Imgur 從 2026 初推行了一波對站長很痛的政策變動。

匿名上傳的圖在 6 個月沒被存取就會被刪。NSFW 內容大清洗刪掉數百萬張,包含一些被誤判的 SFW 圖。對英國 IP 單方面地理封鎖,舊文章直接斷鏈。

對站長來說,這代表你的部落格、論壇個版、PTT 文章裡的 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(PTT / 巴哈 / phpBB) [img]URL[/img] \[img\]URL\[/img\]
Markdown(Hugo / Jekyll / Hexo) ![alt](URL) !\[.*?\]\(URL\)
HTML / WordPress <img src="URL"> <img\s+src=["\']URL["\']
純連結 / Discord embed URL 本身 URL 字串完全比對

PTT WebMode 有點特別。

PTT 文章不能後續編輯,所以「壞圖修復」只能透過貼一篇新的修正文 + 在標題加 [補充]。實測上比較常見的做法是個版 / 部落格直接執行腳本替換、巴哈個版用後台批次編輯、巴哈哈拉版只能補貼修正文、WordPress 用搜尋替換外掛或直接動 wp_posts 表。

剛開始我還以為 PTT 沒救。

後來發現有人寫過爬蟲掃 PTT 個人推文加修正連結 — 但效果有限,因為 PTT 推文也有字數限制。

PTT 那塊就接受損失吧。

第五步:搬到哪個新圖床?

從架構角度,選新圖床要看三條:匿名上傳支援、永久連結(不會 6 個月過期)、批次 API。

實測過比較友善的圖床:

圖床 匿名 API 永久連結 CDN 適合搬家場景
lpic.cc 是 註冊會員後是 台灣 + 全球 中小型部落格、論壇
Catbox 是 是 無 個版、低流量站
ImgChest 是 是 美國 Imgur 替代風格
Postimages 是 是(可選) 歐美 老牌穩定

避開:Imgur(學一次教訓就夠了)、ImgBB(NSFW 政策也在收緊)。

lpic.cc 對搬家場景的設定

從架構角度,lpic.cc 對「圖床搬家」這個場景有三個友善設計。

匿名 API 上傳不用註冊就能 POST,腳本直接接。註冊會員的圖 URL 永久,不會無預警刪。直連友善,不會像 Imgur 強制跳 app — 對 PTT、巴哈這種「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] 語法。

References

#圖床搬家#Imgur#Wayback Machine#BBCode#Markdown#Python 腳本#外連修復#圖床
H

作者

Harvey Zhang

共同創辦人兼 CTO

後端工程師出身,從系統架構角度深度解析圖片託管服務的技術實現。