Nodejs实现定时爬虫的完整实例
事件起因
前两天要帮朋友B站舰长群审核,一个个去舰长列表查找,自然不是一个程序猿的首选,把任务交给计算机让他自己做,摸鱼才是正道。理论成立开始Coding.
由于已知舰长列表的API爬虫使用Axios直接访问接口
于是花了亿点点时间写完了这段爬虫我称之为bilibili-live-captain-tools1.0
constaxios=require('axios')
constroomid="146088"
construid="642922"
consturl=`https://api.live.bilibili.com/xlive/app-room/v2/guardTab/topList?roomid=${roomid}&ruid=${ruid}&page_size=30`
constCaptin={
1:'总督',
2:'提督',
3:'舰长'
}
constreqPromise=url=>axios.get(url);
letCaptinList=[]
letUserList=[]
asyncfunctioncrawler(URL,pageNow){
constres=awaitreqPromise(URL);
if(pageNow==1){
CaptinList=CaptinList.concat(res.data.data.top3);
}
CaptinList=CaptinList.concat(res.data.data.list);
}
functiongetMaxPage(res){
constInfo=res.data.data.info
const{page:maxPage}=Info
returnmaxPage
}
functiongetUserList(res){
for(letitemofres){
constuserInfo=item
const{uid,username,guard_level}=userInfo
UserList.push({uid,username,Captin:Captin[guard_level]})
}
}
asyncfunctionmain(UID){
constmaxPage=awaitreqPromise(`${url}&page=1`).then(getMaxPage)
for(letpageNow=1;pageNow
很明显这个爬虫只能手动触发,直接跑还需要个命令行和node环境,于是就给他用Koa2开了个页面服务,写一个极其简陋的页面
constKoa=require('koa');
constapp=newKoa();
constpath=require('path')
constfs=require('fs');
constrouter=require('koa-router')();
constindex=require('./index')
constviews=require('koa-views')
app.use(views(path.join(__dirname,'./'),{
extension:'ejs'
}))
app.use(router.routes());
router.get('/',asyncctx=>{
ctx.response.type='html';
ctx.response.body=fs.createReadStream('./index.html');
})
router.get('/api/captin',async(ctx)=>{
constUID=ctx.request.query.uid
console.log(UID)
constInfo=awaitindex.main(parseInt(UID))
awaitctx.render('index',{
Info,
})
});
app.listen(3000);
由于页面没有节流防抖,当前版本又只能实时爬取,等待时间较长,频繁刷新自然会触发b站的反爬虫机制,于是当前服务器ip就被风控了。
于是bilibili-live-captain-tools2.0横空出世
functionthrottle(fn,delay){
vartimer;
returnfunction(){
var_this=this;
varargs=arguments;
if(timer){
return;
}
timer=setTimeout(function(){
fn.apply(_this,args);
timer=null;//在delay后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器
},delay)
}
}
再添加节流防抖的同时,使用伪实时爬虫(通过定时任务一分钟爬取一次)
这种情况我们需要去定时执行爬虫脚本了,这个时候我就想到了就可以利用egg的schedule功能了,可是不想让一个爬虫程序如此“大材小用”,遇事不决,百度一下。于是就有了下面的方案
使用NodeSchedule实现定时任务
NodeSchedule是用于Node.js的灵活的cron类和非cron类作业调度程序。它允许您使用可选的重复规则来计划作业(任意函数),以在特定日期执行。它在任何给定时间仅使用一个计时器(而不是每秒钟/分钟重新评估即将到来的作业)。
一、安装node-schedule
npminstallnode-schedule
#或
yarnaddnode-schedule
二、基本用法
一起啊看一下官方给的例子
constschedule=require('node-schedule');
constjob=schedule.scheduleJob('42****',function(){
console.log('Theanswertolife,theuniverse,andeverything!');
});
schedule.scheduleJob的第一个参数需要如下按照规则输入
NodeSchedule规则按下表表示
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ |
│ │ │ │ │ └星期几,取值:0-7,其中0和7都表示是周日
│ │ │ │ └───月份,取值:1-12
│ │ │ └──────日期,取值:1-31
│ │ └─────────时,取值:0-23
│ └────────────分,取值:0-59
└───────────────秒,取值:0-59(可选)
也可以指定一个具体的时间,如:constdate=newDate()
看懂规则我们自己实现一个
constschedule=require('node-schedule');
//定义一个时间
letdate=newDate(2021,3,10,12,00,0);
//定义一个任务
letjob=schedule.scheduleJob(date,()=>{
console.log("现在时间:",newDate());
});
上面的例子就代表到2021年3月10日12点的时候执行报时
三、高级用法
除了基础的用法,我们还可以使用一些更为灵活的方法来实现定时任务。
3.1、隔一分钟执行一次
constschedule=require('node-schedule');
//定义规则
letrule=newschedule.RecurrenceRule();
rule.second=0
//每分钟0秒执行一次
//启动任务
letjob=schedule.scheduleJob(rule,()=>{
console.log(newDate());
});
rule支持设置的值有second、minute、hour、date、dayOfWeek、month、year等。
一些常见的规则如下表
每秒执行
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)模块。我们可以使用定时任务来对服务器系统进行维护,让其在固定的时间段执行某些必要的操作,还可以使用定时任务发送邮件、爬取数据等;
到此这篇关于Nodejs实现定时爬虫的文章就介绍到这了,更多相关Nodejs定时爬虫内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。