翻旧文章时发现好几张图挂了——图床倒闭、对方开了防盗链、原站点改了路径。图片是文章的一部分,图没了文章就废了一半。于是决定把所有外链图片搬到自己服务器。
先摸底
统计一下有多少外链图:
SELECT COUNT(*) FROM wp_posts
WHERE post_content LIKE '%<img%src="http%' AND post_status='publish';
结果 60 多篇里有外链图,涉及 100 多个地址。
下载策略
几个坑要注意:
- 防盗链:有些站点检查 Referer,请求时要带一个正常的 Referer,或者干脆不带
- 超时:不能一个卡住就停,每个请求设 10 秒超时
- 重名:不同站点可能有同名文件,用 URL 的 hash 做文件名
- 格式:webp 兼容性现在没问题,但老主题可能不认,统一转 jpg/png 更稳
脚本核心逻辑:
import hashlib, os, requests
def localize(url, outdir="wp-content/uploads/imported"):
h = hashlib.md5(url.encode()).hexdigest()[:12]
ext = os.path.splitext(url.split("?")[0])[1] or ".jpg"
name = f"{h}{ext}"
path = os.path.join(outdir, name)
if os.path.exists(path):
return "/" + path
r = requests.get(url, timeout=10, headers={"User-Agent": "Mozilla/5.0"})
r.raise_for_status()
with open(path, "wb") as f:
f.write(r.content)
return "/" + path
替换正文
import re
for post in posts:
new = re.sub(r'(<img[^>]+src=")(https?://[^"]+)',
lambda m: m.group(1) + localize(m.group(2)), post["content"])
if new != post["content"]:
update_post(post["id"], new)
改之前一定要备份数据库。我第一次跑的时候正则写得太宽,把 <a href> 的链接也替换了,结果文内链接全指向本地。
关于 SEO
搬图片的时候顺手补 alt 属性。搜索引擎识别图片靠 alt,纯装饰性图片用 alt=""。这个改动对收录有实际帮助,比堆关键词有用。
现在的状态
100 多张图全部落到 wp-content/uploads/imported/,每天随站点一起备份。加载速度也快了——原来要等第三方图床响应,现在跟页面同域,还能走浏览器缓存。
代价是流量和存储。图片总量 300 多 M,对一台小服务器来说还好,但以后如果文章量上来,得考虑对象存储。
- THE END -
最后修改:2023年2月24日
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://mi-blog.cn/archives/668
共有 0 条评论