簡書文章導出
在簡書的設置下面搅轿,就有一鍵導出的按鈕脊奋,可以將 markdown 全部下載到本地熬北。
雖然下載了 markdown,但是在簡書導出內(nèi)容的時候诚隙,圖片并沒有一并導出讶隐,還是簡書內(nèi)部的圖片 URL。所以需要一些手段來進行爬取久又。
創(chuàng)建一個 node 項目
我們將下載下來的文件放到 docs 目錄下巫延,再創(chuàng)建一個 imgs 目錄來存放圖片效五。
|- jianshu
|- docs
|- 開發(fā)日志
|- 01.md
|- 02.md
|- imgs
|- 1.webp
|- 2.webp
|- 3.webp
|- 5.webp
|- index.js
|- package.json
由于用到了 request
來發(fā)起請求,所以需要進行安裝炉峰。
> cd jianshu
> npm init
> yarn add request
使用 node.js 來進行圖片的爬取
下面是完整的爬取代碼畏妖。
let request = require("request");
const fs = require("fs");
// 拿到所有 md 文件路徑
const paths = recursiveQueryFile("./docs");
const allFilePaths = [];
function getFilePaths(arr) {
arr.forEach((item) => {
if (item.children) {
getFilePaths(item.children);
}
if (item.isFile) {
allFilePaths.push(item.path);
}
});
}
getFilePaths(paths.children);
// 拿到所有圖片 URL 路徑
const imgList = [];
allFilePaths.forEach((path) => {
const data = fs.readFileSync(path, "utf-8");
const matchResults = data.match(/!\[\S+\]\(\S+\)/g);
if (matchResults) {
matchResults.forEach((str) => {
let url = str.replace(/!\[\S+\]\(/, "");
url = url.replace(")", "");
imgList.push(url);
});
}
});
console.log("imgList", imgList);
// 逐個請求 URL,并將圖片下載到本地
const map = {};
async function queryAll() {
let i = 1;
for (const url of imgList) {
const imgName = `/imgs/${i}.webp`;
map[url] = imgName;
await request({ url }).pipe(
fs.createWriteStream("." + imgName).on("close", (err) => {
if (err) {
console.log("寫入失敗", err);
} else {
console.log(imgName + " 寫入成功");
}
})
);
i++;
await waitForTimeout(100);
}
console.log("map", map);
await waitForTimeout(100);
replaceUrl();
}
queryAll();
// 遍歷所有 markdown 文件疼阔,替換圖片 URL
function replaceUrl() {
allFilePaths.forEach((path) => {
let data = fs.readFileSync(path, "utf-8");
if (data.match(/!\[\S+\]\(\S+\)/g)) {
Object.keys(map).forEach((key) => {
data = data.replace(key, map[key]);
});
fs.writeFileSync(path, data);
console.log(path + " 保存完畢!");
}
});
}
function waitForTimeout(time) {
return new Promise((resolve, reject) => setTimeout(resolve, time));
}
function recursiveQueryFile(path) {
const children = fs.readdirSync(path);
return {
path,
children: children.map((child) => {
const childPath = path + "/" + child;
const stat = fs.statSync(childPath);
if (stat.isDirectory()) {
return recursiveQueryFile(path + "/" + child);
} else {
return {
path: childPath,
isFile: true,
};
}
}),
};
}
實現(xiàn)步驟
- 遞歸讀取 docs 目錄下所有的文件名稱(非目錄)
- 讀取所有文件內(nèi)容戒劫,通過正則收集 markdown 的圖片鏈接寫法
[name](url)
來奶到圖片 URL - 使用 request 請求圖片,并保存到 imgs 目錄下婆廊。并且為這些圖片另外去一個名稱迅细。
- 記錄下圖片 URL 和圖片名稱的對應關系 map。
- 通過對應關系 map 將所有 markdown 文件中的圖片 URL淘邻。
最后
一開始選擇簡書是因為它簡潔清爽的界面疯攒、好用的 markdown 編輯器、快速上傳圖片這三個功能列荔。后來又用上了日更的功能敬尺,堅持日更的確讓我收獲頗豐。
但是贴浙,現(xiàn)在的簡書無論是網(wǎng)頁端還是 APP 都充斥著廣告砂吞,讓人很不爽。而且再簡書上傳的圖片無法直接在其他網(wǎng)站使用崎溃,導致我往往需要上傳兩遍圖片蜻直,也是很惡心人的一點。
最近突然有了自己搞個類似簡書的網(wǎng)站的想法袁串,來避開簡書的這些惡心人的事情概而。所以選擇導出文章搬家~