Yard


用nodejs自动化保存每日bing美图?

特别喜欢bing的每日美图,所以每天日常都是去bing保存下每日更新的那张图片,然后在一次朋友圈回复下---“你为什么不搞成自动化,每天保存不累???”,开始了这次的代码之旅。先贴上github地址:https://github.com/YardWill/get-bing-bg

###一、找接口 在一些大型网站上的比较大的背景图片都是异步加载的,在bing上也验证了一下,在网速慢的情况下,背景显示的是黑色,之后才显示图片。所以我想,图片地址应该是从接口返回,之后异步加载的。然后去使用chrome的调试工具Network,在里面发现了这样一个接口:http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN 点开来一看你就知道,图片信息都在里面。

图片接口

###二、得到图片并保存 这里使用的是request模块,也是比较常用的取接口内容的模块。

const request = require('request');
const fs = require('fs');
const path = require('path');

request.get('http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN', (error, response, body) => {
    const img = JSON.parse(body).images[0];
    const arr = img.url.split('/');
    const str = arr[arr.length - 1];
    request(img.url).pipe(fs.createWriteStream(path.join('./img', str)));
    console.log(`${new Date()}${str} is ok!`);
});

代码其实很简单 先将img的资源取出来,然后使用fs文件模块将img资源放到目录下的'img'文件夹内。

但是问题来了,这下代码只是用来保存当前一天的图片存到文件夹里,每天还是得敲一个node app.js才能获取图片,和之前的右键保存并没提升多少效率。

###三、定时任务 既然要每天跑一次,那么我们使用定时任务去做不就好了,这里又使用了一个新的模块叫node-schedule。 node-schedule是专门用来做定时任务的,详情可以去看官方文档,我这里就只简单的贴下代码。

const schedule = require('node-schedule');

const rule = new schedule.RecurrenceRule();
rule.dayOfWeek = [0, new schedule.Range(1, 6)];
rule.hour = 8;
rule.minute = 0;

schedule.scheduleJob(rule, () => {
    require('./src/get.js');
});

那么问题又来了,我总不能每天都开着电脑吧?解决方法其实很简单,放到服务器去执行不就行了。但是放在服务器我本地怎么用壁纸呢?这个更简单了,直接使用git,同步壁纸呀! 一个git pull 命令所有之前保存的图片就都来了!!

###四、服务器执行代码,并自动上传git 在node内使用git命令行,我们又需要一个模块child_process,这个模块是node自带的,可以直接使用。

const childProcess = require('child_process');

const cmd = (c) => c;
const shell = 'bash';
const config = {
    env: {
        NODE_ENV: 'production',
        encoding: 'utf8',
    },
    shell,
};

const exec = (c) => {
    return new Promise((resolve, reject) => {
        childProcess.exec(c, config, (err, stdout, stderr) => {
            if (err) {
                reject(err);
            } else {
                resolve(stdout, stderr);
            }
        });
    });
};

console.log('Deploy start.');
exec(cmd('git status'))
    .then(() => exec(cmd('git add .')))
    .then(() => exec(cmd('git commit -m "ss"')))
    .then(() => exec(cmd('git push -u origin master')))
    .then(() => console.log('Deploy end.'))
    .catch(err => {
        console.error(err);
    });

这里的代码略微多了一点,但其实也很简单,就是让node去执行命令行,所有的命令行都在最下面。

###五、上线 将代码放置服务器运行,执行request改为如下:

const request = require('request');
const fs = require('fs');
const path = require('path');

request.get('http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=zh-CN', (error, response, body) => {
    const img = JSON.parse(body).images[0];
    const arr = img.url.split('/');
    const str = arr[arr.length - 1];
    request(img.url).pipe(fs.createWriteStream(path.join('./img', str)));
    setTimeout(() => {
        require('./cmd.js');
    }, 20000);
    console.log(`${new Date()}${str} is ok!`);
});

这里的20s延迟是为了确保fs将文件保存完再进行git上传的一种简单的处理方式。当然还有其他解决方案,这样粗暴的解决只是因为这是个定时任务,对时间没有什么要求。

###六、验收成果 几天之后在本地

git pull

这几天保存的壁纸都存到了本地! 真的很爽!

目前代码只能运行在*nix上,而且还没做很多git的容错处理,以后发现问题再进行修复吧。windows用户如果只是获取壁纸也只需要git pull命令即可。对代码不是很清晰的话,可以借助github内容进行解读,因为觉得比较简单,所以就没做多少注释。