一直垂涎網路爬蟲程式,但是俺只是一個渣渣前端,對爬蟲真是難以下手啊,當第一次聽到了node這奇葩可以用js去寫後端的時候,就想著能不能用node去實現爬蟲呢?知道可以的我,就像20幾年的俺頭一次看見了黃花大閨女一般,情難自抑~ 於是乎我本人:
幹勁 +100
興趣 +100
但是啊!!關鍵是
不懶惰 +0
懶屬性一點依然“皮實”,所以遲遲也沒有開始上手去做爬蟲...
直到!上週看海賊王不過癮,決定看漫畫,但是網路不好啊,看的鬧心,於是就終於痛定思痛,寫下了 let http = require('http');
昨天終於寫完了,就分享給對這個感興趣的小夥伴吧~
let http = require('http');
let colors = require('colors');
let fs = require('fs');
let cheerio = require('cheerio');
const INIT = {
pagePath: '/02/Vol_001/index_0.html',
mounts: 100000
}
if(process.argv.length !== 2) {
let begin, mounts;
process.argv.forEach(item => {
if (item.includes('begin')) {
begin = item.split('=')[1]
}
if (item.includes('mounts')) {
mounts = item.split('=')[1]
}
})
INIT.pagePath = begin ? String(begin) : INIT.pagePath;
INIT.mounts = mounts ? Number(mounts) : INIT.mounts;
}
// 初始頁資訊
let pageInfo = {
hostname: 'manhua.fzdm.com',
path: INIT.pagePath
}
// 初始圖片資訊
let imgInfo = {
hostname: 'p0.xiaoshidi.net',
path: ``
}
/**
* @description 請求當前頁面資訊
* @param {Object} pageInfo - 初始頁資訊
* @param {string} pageInfo.hostname - 頁域名地址
* @param {string} pageInfo.path - 路徑
*/
let getPageInfo = (address) => {
let client = http.request({
hostname: address.hostname,
path: address.path
}, (res) => {
let contents = '';
res.on('data', (callbackData) => {
console.log('=======響應開始'.red);
contents += callbackData;
})
res.on('end', () => {
let $ = cheerio.load(contents);
let sContentsInfo = (/<script type="text\/javascript">(.+?Title.+?)<\/script>/).exec(contents)[1];
// 獲取當頁圖片的地址
let mhurl = (/mhurl="(.+?)\.jpg\"/).exec(sContentsInfo);
imgInfo.path = '/' + mhurl[1] + '.jpg'; console.log(imgInfo.path)
lineDetail(imgInfo.path)
// 獲取下一頁地址
let nextPage = $('.navigation').children().last().prop('href');
pageInfo.path = `/${(/Clid="(.+?)\"/).exec(sContentsInfo)[1]}\/${(/Url="(.+?)\"/).exec(sContentsInfo)[1]}/${nextPage}`; console.log(pageInfo.path)
// 圖片名字生成
let imgName = mhurl[1].replace(/\//g,'_').replace(/\d+\_/,'').replace(/[a-zA-Z]+/,'');
console.log(imgName.cyan);
// 儲存圖片
downloadImg(imgInfo, imgName)
console.log('=======響應結束'.red);
})
})
client.end();
client.on('error', (err) => {
console.log(err);
})
}
/**
* @description 圖片質量線路檢測切換(from source code)
* @param {string} mhurl - 圖片地址
* @param {string} mhurl - 線路
* @returns {string} 返回優質圖片地址
*/
function lineDetail(mhurl, mhss = 'p1.xiaoshidi.net') {
let mhpicurl = '';
if (mhurl.indexOf("2015") != -1 || mhurl.indexOf("2016") != -1 || mhurl.indexOf("2017") != -1 || mhurl.indexOf("2018") != -1) {
} else {
mhss = mhss.replace(/p1/, "p0").replace(/p2/, "p0").replace(/p07/, "p17")
}
mhpicurl = mhss + "" + mhurl;
if (mhurl.indexOf("http") != -1) {
fs.writeFile(`./one-piece/${mhurl.split('://')[1]}.text`, `${mhurl}下的圖片無法抓取,請手動檢視吧~`, (err) => {
console.log(err);
})
mhpicurl = 'p17.xiaoshidi.net/2/Vol_001/001aa.jpg'
}
return mhpicurl;
}
/**
* @desc 下載圖片並儲存
* @param { any } info 圖片地址資訊
* @param { string } name 圖片儲存的名字
*/
function downloadImg(info, name) {
let client = http.request({
hostname: info.hostname,
path: info.path
},(res) => {
res.setEncoding('binary');
let contents = '';
res.on('data', (backData) => {
contents += backData;
})
res.on('end', () => {
// 沒有 one-piece 資料夾則新建一個
fs.access('./one-piece', (err) => {
if(err) fs.mkdirSync('./one-piece');
fs.writeFile(`./one-piece/${name}.jpg`, contents, 'binary', (err) => {
if(err) throw err;
console.log('圖片已儲存'.green);
})
})
})
})
client.end();
client.on('error', (e) => {
console.log(e)
})
}
// 執行爬蟲
let i = 1;
let t = setInterval(() => {
if (i >= INIT.mounts) clearInterval(t);
getPageInfo(pageInfo);
i++;
},1300)
複製程式碼
本人的註釋還是寫得比較完備的,有什麼不明白的小夥伴可以我們們探討探討。
附上github地址,使用方法在內有寫 github.com/Luooojunnn/… 喜歡的小夥伴請給俺人生中第一個star好嗎?俺會持續更新一些有意思的爬蟲~