Node爬取大批量文件

Node爬取大批量文件

有個朋友在搞留學工做室,常常訪問的一個網站叫留學者指南,然而每次都要去訪問該網站,顯得極其不專業。因而託俺幫忙寫腳本去爬他家的東西,我觀察了下,此次,咱們要爬的東西就有點多了——大概就20多萬個文件吧~~~html

在20多萬個文件中,下載極有可能會被中斷,所以須要作下載進度備份,下載進度恢復。數組

那麼針對這樣子的需求,咱們開始吧!app

上代碼!網站

const cheerio = require("cheerio"); //用於處於HTML文檔流,用法相似jQuery
const http = require("http"); //用於發起請求
const fs = require("fs"); //用於檢測、寫入文件等其餘文件操做

// "http://www.compassedu.hk/sitemap1.txt",
// "http://www.compassedu.hk/sitemap2.txt", //重複的連接
var source = [ //Robots.txt顯示的數據源
    "http://m.compassedu.hk/sitemap3.txt",
    "http://m.compassedu.hk/sitemap4.txt",
    "http://m.compassedu.hk/sitemap6.txt",
    "http://m.compassedu.hk/sitemap7.txt",
    "http://m.compassedu.hk/sitemap8.txt"
]
var s = 0; //控制源的序號
var arr = []; //合併的下載地址數組
var sou = []; //源下載地址數組
var i = 0; //當前下載地址數組序號

fs.exists(__dirname+"/compassedu", function(flag){ //下載路徑檢測
    if(!flag) fs.mkdirSync(__dirname+"/compassedu"); //建立下載存放目錄
})
fs.exists(__dirname+"/logs", function(flag){ //日誌路徑檢測
    if(!flag) fs.mkdirSync(__dirname+"/logs"); //建立日誌存放目錄
})

if(fs.existsSync(__dirname+"/logs/compassedu_backup")){ //是否存在斷連恢復下載的控制文檔
    let obj = JSON.parse(fs.readFileSync(__dirname+"/logs/compassedu_backup")); //存在則讀取上次下載的位置
    i = obj.index;
    init(); //開始初始化程序
}
else{
    init(); //開始初始化程序
}

function init(){ //初始化
    http.get(source[s], function(res){ //獲取源下載地址文件

        //將源文件的內容存儲到數組
        let rawData = "";
        res.setEncoding("utf8");
        res.on("data", function(chunk){ //監聽數據流
            rawData += chunk;
        });
        res.on("end", function(){ //監聽結束
            sou[s] = rawData.split("\n");
            console.log("源", s+1, ": ", sou[s].length, "條數據");
            s++;
            if(s<source.length){ //源文件還未讀取完
                init();
            }
            else{ //源文件讀取完畢
                for(let m=0;m<sou.length;m++){ //將全部的地址數組合並
                    arr = arr.concat(sou[m]);
                }
                arr = [...new Set(arr)]; //去重
                console.log("總計: ", arr.length, "條數據", "\n爬蟲配置完畢!!\n開始爬取 >>");
                start(); //開始爬取程序
            }
        });
    })
}

function start(){ //開始
    let url = arr[i];
    console.log(url); //打印當前爬取的URL
    
    http.get(url,function(res){ //發起請求
        let obj = { //將當前的信息存儲到對象中
        	"time": new Date().toLocaleTimeString(),
            "index": i,
            "url": url,
            "status": res.statusCode
        };
        fs.appendFileSync("./logs/download.log", JSON.stringify(obj), "utf8"); //寫入日誌文件
        fs.writeFileSync("./logs/compassedu_backup", JSON.stringify({"index": i}), "utf8"); //將當前的下載URL序號寫入斷連恢復文件
        //讀取請求到的數據流
        let rawData = "";
        res.setEncoding("utf8");
        res.on("data", function(chunk){ //監聽數據流事件
            rawData += chunk;
        });
        res.on("end", function(){ //監聽結束事件
            $ = cheerio.load(rawData); //啓用類jQuery插件
            title = $(".container-public h1").text().replace(/\s/,"").trim(); //讀取數據流部分的標題
            body = $(".container-public").html(); //讀取數據流部分的內容
            body = body.split("visible-xs")[0]; //剝離多於的數據或其餘處理,準備寫入文件
            i++; //序號+1
            fs.writeFile(__dirname+"/compassedu/"+title+".html", body, "utf8", function(err){ //將處理好的數據寫入文件
                if(!err) console.log(title, "寫入成功");
                else{
                    console.log(err);
                }
            });
            if(i>=arr.length) { //若序號達到數組的最後,結束程序
                console.log("爬取結束");
                fs.unlinkSync("./logs/compassedu_backup");//爬取結束,銷燬斷連恢復文件
                return;
            }
            else { //不然遞歸運行
                start();
            }
        });
        res.on("error", function(err){ //監聽其餘錯誤
            console.log(err);
        });
    })
}
複製代碼

至此,就結束了,是否有bug還不清楚,數據還沒爬完呢~ui

有bug的話,我後續補充修復~url

相關文章
相關標籤/搜索