最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Nodejs 实现定时爬虫

    正文概述 掘金(咸鱼爱前端)   2021-03-11   889

    事件起因

    前两天要帮朋友B站舰长群审核,一个个去舰长列表查找,自然不是一个程序猿的首选,把任务交给计算机让他自己做,摸鱼才是正道。理论成立开始Coding .

    于是花了亿点点时间写完了这段爬虫我称之为bilibili-live-captain-tools 1.0

    const axios = require('axios')
    const roomid = "146088"
    const ruid = "642922"
    const url = `https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList?roomid=${roomid}&ruid=${ruid}&page_size=30`
    
    const Captin = {
        1: '总督',
        2: '提督',
        3: '舰长'
    }
    
    const reqPromise = url => axios.get(url);
    
    let CaptinList = []
    let UserList = []
    
    async function crawler(URL, pageNow) {
        const res = await reqPromise(URL);
        if (pageNow == 1) {
            CaptinList = CaptinList.concat(res.data.data.top3);
        }
        CaptinList = CaptinList.concat(res.data.data.list);
    }
    
    
    function getMaxPage(res) {
    
        const Info = res.data.data.info
        const { page: maxPage } = Info
        return maxPage
    }
    
    
    function getUserList(res) {
    
        for (let item of res) {
            const userInfo = item
            const { uid, username, guard_level } = userInfo
            UserList.push({ uid, username, Captin: Captin[guard_level] })
        }
    }
    
    async function main(UID) {
        const maxPage = await reqPromise(`${url}&page=1`).then(getMaxPage)
        for (let pageNow = 1; pageNow < maxPage + 1; pageNow++) {
            const URL = `${url}&page=${pageNow}`;
            await crawler(URL, pageNow);
        }
        getUserList(CaptinList)
        console.log(search(UID, UserList))
        return search(UID, UserList)
    }
    
    function search(uid, UserList) {
        for (let i = 0; i < UserList.length; i++) {
            if (UserList[i].uid === uid) {
                return UserList[i];
            }
        }
        return 0
    }
    
    module.exports = {
        main
    }
    

    很明显这个爬虫只能手动触发,直接跑还需要个命令行和node环境,于是就给他用Koa2开了个页面服务,写一个极其简陋的页面

    const Koa = require('koa');
    const app = new Koa();
    const path = require('path')
    const fs = require('fs');
    const router = require('koa-router')();
    const index = require('./index')
    const views = require('koa-views')
    
    
    
    app.use(views(path.join(__dirname, './'), {
        extension: 'ejs'
    }))
    app.use(router.routes());
    
    router.get('/', async ctx => {
        ctx.response.type = 'html';
        ctx.response.body = fs.createReadStream('./index.html');
    })
    
    router.get('/api/captin', async (ctx) => {
        const UID = ctx.request.query.uid
        console.log(UID)
        const Info = await index.main(parseInt(UID))
        await ctx.render('index', {
            Info,
        })
    });
    
    app.listen(3000);
    

    由于页面没有节流防抖,当前版本又只能实时爬取,等待时间较长,频繁刷新自然会触发b站的反爬虫机制,于是当前服务器ip就被风控了。

    于是bilibili-live-captain-tools 2.0横空出世

    function throttle(fn, delay) {
        var timer;
        return function () {
            var _this = this;
            var args = arguments;
            if (timer) {
                return;
            }
            timer = setTimeout(function () {
                fn.apply(_this, args);
                timer = null; // 在delay后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器
            }, delay)
        }
    }
    

    再添加节流防抖的同时,使用伪实时爬虫(通过定时任务一分钟爬取一次)

    这种情况我们需要去定时执行爬虫脚本了,这个时候我就想到了就可以利用eggschedule功能了,可是不想让一个爬虫程序如此“大材小用”,遇事不决,百度一下。于是就有了下面的方案

    使用 Node Schedule 实现定时任务

    一、安装 node-schedule

    npm install node-schedule
    # 或
    yarn add node-schedule
    

    二、基本用法

    一起啊看一下官方给的例子

    const schedule = require('node-schedule');
    
    const job = schedule.scheduleJob('42 * * * *', function(){
      console.log('The answer to life, the universe, and everything!');
    });
    

    schedule.scheduleJob 的第一个参数需要如下按照规则输入

    Node Schedule规则按下表表示

    *  *  *  *  *  *
    ┬  ┬  ┬  ┬  ┬  ┬
    │  │  │  │  │  |
    │  │  │  │  │  └ 星期几,取值:0 - 7,其中 0 和 7 都表示是周日
    │  │  │  │  └─── 月份,取值:1 - 12
    │  │  │  └────── 日期,取值:1 - 31
    │  │  └───────── 时,取值:0 - 23
    │  └──────────── 分,取值:0 - 59
    └─────────────── 秒,取值:0 - 59(可选)
    也可以指定一个具体的时间,如:const date = new Date()
    

    看懂规则我们自己实现一个

    const schedule = require('node-schedule');
    
    // 定义一个时间
    let date = new Date(2021, 3, 10, 12, 00, 0);
    
    // 定义一个任务
    let job = schedule.scheduleJob(date, () => {
      console.log("现在时间:",new Date());
    });
    

    上面的例子就代表到2021年3月10日12点的时候执行报时

    三、高级用法

    除了基础的用法,我们还可以使用一些更为灵活的方法来实现定时任务。

    3.1、隔一分钟执行一次

    const schedule = require('node-schedule');
    
    // 定义规则
    let rule = new schedule.RecurrenceRule();
    rule.second = 0
    //每分钟 0 秒执行一次
    
    // 启动任务
    let job = schedule.scheduleJob(rule, () => {
      console.log(new Date());
    });
    

    rule 支持设置的值有 secondminutehourdatedayOfWeekmonthyear 等。 一些常见的规则如下表

    每秒执行
    rule.second = [0,1,2,3......59];
    每分钟 0 秒执行
    rule.second = 0;
    每小时 30 分执行
    rule.minute = 30;
    rule.second = 0;
    每天 0 点执行
    rule.hour =0;
    rule.minute =0;
    rule.second =0;
    每月 1 号的 10 点执行
    rule.date = 1;
    rule.hour = 10;
    rule.minute = 0;
    rule.second = 0;
    每周一、周三、周五的 0 点和 12 点执行
    rule.dayOfWeek = [1,3,5];
    rule.hour = [0,12];
    rule.minute = 0;
    rule.second = 0;
    

    四、终止任务

    可以使用 cancel() 终止一个运行中的任务。当任务出现异常及时取消终止任务

    job.cancel();
    

    总结

    node-schedule 是 Node.js 的一个 定时任务(crontab)模块。我们可以使用定时任务来对服务器系统进行维护,让其在固定的时间段执行某些必要的操作,还可以使用定时任务发送邮件、爬取数据等;

    ❤️ 感谢大家

    如果你觉得这篇内容对你挺有有帮助的话:

    点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)

    关注公众号咸鱼爱前端,我们一起学习一起进步。

    觉得不错的话,也可以阅读其他文章(感谢朋友的鼓励与支持???):

    css 世界学习总结 - 第三章 流、元素与基本尺寸

    React-Query 让你的状态管理更优雅

    前端页面布局学习神器

    参考链接:

    github.com/node-schedu…

    eggjs.org/zh-cn/basic…


    起源地下载网 » Nodejs 实现定时爬虫

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元