一直垂涎网络爬虫程序,但是俺只是一个渣渣前端,对爬虫真是难以下手啊,当第一次听到了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好吗?俺会持续更新一些有意思的爬虫~