fix: 修复博客图片加载失败(掘金防盗链)
- 将《Git使用教学》中的掘金外链图片下载至 source/images/ 并替换为站内路径 - _config.yml 注入 no-referrer meta 作为兜底方案 - 新增 tools/download-juejin-images.js 批量下载/替换脚本
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
// 下载 Markdown 中的掘金外链图片到 source/images/,并替换链接为站内路径
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
|
||||
const ROOT = 'c:/Users/Administrator/Desktop/新建文件夹/blog';
|
||||
const MD = path.join(ROOT, 'source/_posts/Git使用教学.md');
|
||||
const OUT = path.join(ROOT, 'source/images');
|
||||
|
||||
function download(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const lib = url.startsWith('https') ? https : http;
|
||||
const req = lib.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
|
||||
// 跟随重定向
|
||||
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
res.resume();
|
||||
return download(new URL(res.headers.location, url).href).then(resolve, reject);
|
||||
}
|
||||
if (res.statusCode !== 200) {
|
||||
res.resume();
|
||||
return reject(new Error('HTTP ' + res.statusCode));
|
||||
}
|
||||
const chunks = [];
|
||||
res.on('data', (c) => chunks.push(c));
|
||||
res.on('end', () => resolve(Buffer.concat(chunks)));
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.setTimeout(30000, () => req.destroy(new Error('timeout')));
|
||||
});
|
||||
}
|
||||
|
||||
(async () => {
|
||||
fs.mkdirSync(OUT, { recursive: true });
|
||||
let content = fs.readFileSync(MD, 'utf8');
|
||||
|
||||
const re = /!\[[^\]]*\]\((https:\/\/p3-juejin\.byteimg\.com\/[^)\s]+)\)/g;
|
||||
const map = {}; // url -> /images/xxx.webp
|
||||
let m;
|
||||
const tasks = [];
|
||||
|
||||
while ((m = re.exec(content)) !== null) {
|
||||
const url = m[1];
|
||||
if (map[url]) continue;
|
||||
const seg = url.split('/').pop();
|
||||
const hash = seg.split('~')[0];
|
||||
if (!hash) {
|
||||
console.log('跳过(无法解析文件名): ' + url);
|
||||
continue;
|
||||
}
|
||||
const file = hash + '.webp';
|
||||
map[url] = '/images/' + file;
|
||||
tasks.push(
|
||||
download(url)
|
||||
.then((buf) => {
|
||||
fs.writeFileSync(path.join(OUT, file), buf);
|
||||
console.log('[OK] ' + file + ' <- ' + url);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log('[FAIL] ' + url + ' -> ' + e.message);
|
||||
delete map[url];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
await Promise.all(tasks);
|
||||
|
||||
for (const url in map) {
|
||||
content = content.split(url).join(map[url]);
|
||||
}
|
||||
fs.writeFileSync(MD, content); // UTF-8 无 BOM
|
||||
|
||||
console.log('\n完成:处理 ' + Object.keys(map).length + ' 张图片');
|
||||
})();
|
||||
Reference in New Issue
Block a user