公司使用的bug管理工具是禅道,苦于禅道没开通bug通知功能,出现自己的Bug时不能及时通知,但领导又要求随时查看禅道解决问题,一不留神就漏掉,就想着用脚本来实现通知功能,真佩服我自己啊哈哈!!!

1、部署环境

华为云服务器centerOS

2、代码环境

Node服务、Pm2进程保持工具

3、所需插件

superagent:请求访问
cheerio:类似于JQ
Core :阿里云短信服务
sd :时间格式转换工具
fs :文件读写工具
schedule :定时任务工具
logger :日志记录工具

4、思路整理

首先手动登录到禅道,跳转到分配给bug的页面,并从浏览器的获取到登录页面和bug页面地址和cookie信息,然后通过爬虫定时发起ajax请求去登录禅道,然后将cookie通过fs写入记事本,再次发送请求抓取到bug页面,通过cheeio处理拿到bug条数,通过与存入的上次条数对比,最后通过短信、邮件服务发送通知,并启动定时程序,及时写入日志。

5、代码实现

5.1:登录实现

var loginurl = '**********' ;
var browserMsg={
  "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
  'Content-Type':'application/x-www-form-urlencoded'
};
superagent.post(loginurl).set(browserMsg)
      .type('form')
      .send({
        'name': '',
        'password': ''
      })
    .end(function (err, res) {
      var cookie = res.headers["set-cookie"];
      fs.writeFile('./cookie.txt', cookie, function (err, data) {
        if (err) {
          logger.error("cookie写入错误:" + err);
        } else {
          logger.info("cookie写入成功");
          getData();
        }
      })
  })

5.2:抓取bug条数实现

const targeturl="************";
const browserMsg="见上面代码块"

fs.readFile('./cookie.txt', "utf8", function (err, data) {
    if (err) {
      logger.error("cookie读取错误:" + err);
    } else {
      var cookie = data.toString();
      logger.info("cookie读取成功:" + cookie);
      //传入cookie
    superagent.get(targeturl).set("Cookie", cookie).set(browserMsg).end(function (err, res) {
      if (err) {
        getCookie()       //cookie失效重新获取cookie
      }
    let $ = cheerio.load(res.text);
       /*
       html分析处理(略)
       获取到最新的bug条数 newcount
       获取记事本的原来的bug数 oldcount
       */
        if (newcount > oldcount) {
          fs.writeFile('./a.txt', newcount, function (err, data) {
            if (err) {
              logger.error("写入文件错误:" + err);
            } else {
              logger.info("写入文件成功");
            }
          })
         /*
        如果旧的大于等于新的,退出本次bug抓取
        否则将新的写入文本,并处理拼接bug号 codestr 和bug描述 contentstr,
        调用邮件和短信服务,获取当前时间传入
        */
          var time = sd.format(new Date(), 'YYYY-MM-DD HH:mm:ss');
          sendSMS("邮件前缀", time, contentstr, codestr);
          sendEmail(codestr,contentstr)
        }
      }
    })
  })
    }
  })

5.3:邮件服务

作者在这里使用的是阿里云的api,具体请参照阿里云官方api

var transporter = nodemailer.createTransport({
  service: '******',  //邮件服务厂商
  port: ******,       //端口
  secureConnection: true,
  auth: {         //邮件发件地址和授权码
    user: '******',   
    pass: '******',
  }
});
let mailOptions = {
    from: '邮箱头部', //"示例" 
    to: '收件地址',
    subject: '邮件主题',
    html: '拼好的bug号和bug描述'
  };
  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      logger.error("邮件发送失败:"+error);
    }
    logger.info("邮件发送成功");
    logger.info("执行任务结束-------");
  });

5.4:短信服务

作者在这里使用的是阿里云的api,具体请参照阿里云官方api

var client = new Core({
  accessKeyId: '*****',   //阿里云接入key,具体会在注册短信服务时提示
  accessKeySecret: '*****',//阿里云接入密钥,具体会在注册短信服务时提示
  endpoint: '*****',   //服务地址,具体会在注册短信服务时提示
  apiVersion: '*****' //服务版本,具体会在注册短信服务时提示
});
var params = {
    "RegionId": "cn-hangzhou",   //服务地址
    "PhoneNumbers": "*****", //手机号
    "SignName": "*****",        //与短信服务签名一致
    "TemplateCode": "*****", //与模板编号一致
  }
//根据模板调整对应模板参数字段
  var json = {
    //***
    //ex:"name": name,
    //*** 
  }
  json=JSON.stringify(json)
  params["TemplateParam"] = json;

  var requestOption = {
    method: 'POST'  //请求方式
  };

  client.request('SendSms', params, requestOption).then((result) => {
    logger.debug(JSON.stringify(result));
    logger.info("短信发送成功-------");
  }, (ex) => {
    logger.error("短信发送失败:"+ex);
  })

5.5:日志服务

const log4js = require('log4js');
log4js.configure({
    appenders: {
        xcLogFile: {
            type: "dateFile",
            filename: './logs/log',//日志的路径
            alwaysIncludePattern: true,//(默认为false) -
            //compress: true,//(默认为false) -压缩备份文件(备份文件将具有.gz扩展名)
            pattern: "-yyyy-MM-dd-hh.log",//(可选,默认为.yyyy-MM-dd) - 用于确定何时滚动日志的模式。
            encoding: 'utf-8',//default "utf-8",编码
            maxLogSize: 100000 //文件最大存储空间,
        },
        xcLogConsole: {
            type: 'console'
        }
    },
    categories: {
        default: {
            appenders: ['xcLogConsole','xcLogFile'],
            level: 'all'
        },
    }
});

5.6:定时服务

var rule = new schedule.RecurrenceRule();
rule.minute = [10, 20, 30, 40, 50]; //每小时的10、20、30、40、50触发
schedule.scheduleJob(rule, function () {
 //操作
});

6、总结

第一个试手爬虫,逻辑处理不怎么严密,本来想借助mySQL实现,但当时工作任务多,暂时以记事本代替,整体较为简单。

Tokials

月亮被嚼碎了变成星星,你就藏在漫天的星光里。

Tokials

月亮被嚼碎了变成星星,你就藏在漫天的星光里。