俺寻思这node版的漫画爬虫没人要捏...

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

转载于:https://juejin.im/post/5b814aff6fb9a019d20e1b6f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值