phenomLi / Blog

Comments, Thoughts, Conclusions, Ideas, and the progress.
219 stars 17 forks source link

node自定义模块:一个壁纸下载小工具 #4

Open phenomLi opened 6 years ago

phenomLi commented 6 years ago

作为微软忠实用户,Windowsphone,win8,win10一路走来,一直都很喜欢里面的一样东西,就是bing提供的锁屏壁纸,都很唯美。网络上已经有很多很成熟的bing壁纸下载工具了,但是这次我决定自己做一个,以node模块形式的,虽然很简陋,但是这不重要,贵在学到东西。
首先确保电脑已经安装node和npm环境

第一步:编写主代码

首先先要把获取bing壁纸的api找出来,我在网上找到一个

http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1
访问后浏览器返回了如下信息:

{
    "images":
    [{
        "startdate":"20170920",
        "fullstartdate":"201709201600",
        "enddate":"20170921",
        "url":"/az/hprichbg/rb/CorricellaMarina_ZH-CN11169480773_1920x1080.jpg",
        "urlbase":"/az/hprichbg/rb/CorricellaMarina_ZH-CN11169480773",
        "copyright":"普罗奇达岛,意大利那不勒斯湾 (© Frank Chmura/age fotostock)",
        "copyrightlink":"http://www.bing.com/search?q=%E6%99%AE%E7%BD%97%E5%A5%87%E8%BE%BE%E5%B2%9B&form=hpcapt&mkt=zh-cn",
        "quiz":"/search?q=Bing+homepage+quiz&filters=WQOskey:%22HPQuiz_20170920_CorricellaMarina%22&FORM=HPQUIZ",
        "wp":true,
        "hsh":"d2bbe5539a47b4d03a5bc541d09a9ecf",
        "drk":1,
        "top":1,
        "bot":1,
        "hs":[]
    }],
    "tooltips":{
        "loading":"正在加载...",
        "previous":"上一个图像",
        "next":"下一个图像",
        "walle":"此图片不能下载用作壁纸。",
        "walls":"下载今日美图。仅限用作桌面壁纸。"
    }
}

里面响应的是一个json格式的数据,我们先要把里面有用的东西提取出来。比如里面的url,还有copyright,用作保存的图片的名字。那么现在我们可以开始写代码了:

const http = require('http'),  //引入http模块用作请求信息
      fs = require('fs');       //引入fs模块用作读写文件

首先我们引入需要用到的模块,一个是http模块一个是fs模块,然后我们就可以请求内容了:

http.get('http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1', res => {

});

使用http的get方法可以请求一个url,在回调函数里面的res(response)可以监听到响应的数据,但是由于http协议的限制,数据只能一分一分传过来。用res监听data事件可以获取需要的数据,当所有数据传送完毕则会响应end事件,于是我们可以这样写:

http.get('http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1', res => {

    let chunk = '',
        data = '',
        url = '',
        copyright = '';

    //res响应data事件,不断接收数据
    res.on('data', data => {
        chunk += data;
    });

    //res接收数据完毕,提取需要的信息
    res.on('end', data => {

        //接收到的json为String,先解析为Object
        data = JSON.parse(chunk);
    });

});

获取到响应的json数据,那我们就可以提取其中我们需要的内容了,这部分很简单:

http.get('http://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1', res => {

    let chunk = '',
        data = '',
        url = '',
        copyright = '';

    //res响应data事件,不断接收数据
    res.on('data', data => {
        chunk += data;
    });

    //res接收数据完毕,提取需要的信息
    res.on('end', data => {

        //接收到的json为String,先解析为Object
        data = JSON.parse(chunk);

        //提取内容
        url = data.images[0].url;
        copyright = data.images[0].copyright;

    });
});

我们把url和copyright都打印出来看看是什么样子:

很好,现在需要的信息都拿到了。但是我们现在拿到的只是一个url,我们要的是把url里面的图片文件下载下来,很显然我们要再进行一次http请求。为了避免进入callback hell,我再另外定义一个downloader函数,具体思路和上面大同小异:

const downloader = (url, copyright, callback) => {
    //当我尝试直接访问url的时候却显示找不到文件,一番折腾之后,发现原来要在url前面加上bing的主机名
    http.get('http://s.cn.bing.net' + url, res => {

        let pic = '';

        //设置数据格式为二进制
        res.setEncoding('binary');

        //res响应data事件,不断接收数据
        res.on('data', data => {
            pic += data;
        });

        //res接收数据完毕,提取需要的信息
        res.on('end', () => {

            //写入磁盘
            fs.writeFile('./bing/' + copyright + '.jpg', pic, 'binary', err => {
                if(!err){

                    //执行回调
                    callback();
                }
            });
        });
    });
};

需要注意的是,要先把数据格式设为二进制格式,不然没法识别。 最后在主方法那里调用downloader函数:

downloader(url, copyright, () => {
      console.log('图片保存成功.');
});

现在看起来程序应该是没问题了,跑起来试试: 可以看到bing文件夹下面也成功新增了图片:

到此,主程序完成。


第二步:包装为node模块

这部分十分简单,我们可以用module.exports将函数或对象包装成commonjs模块,所以我们在主程序作以下修改:

module.exports = function() {
  //主程序。。。
};

这样就可以了。我们新建一个文件,尝试引入并调用这个我们自己定义的模块:

const wallpaperDownloader = require('./new');    //引入模块

wallpaperDownloader();

运行看看效果: 很明显是没有问题的。

第三步:将模块分享到npm

写好了模块之后,我们可以用npm工具把模块分享到npm官网。 首先要在npm官网注册好账号,然后在命令行使用

$ npm login

登录账号,之后再用

$ npm init

为你的模块设置一些基本信息,最后用

$ npm publish

发布你的模块,以上步骤都很简单,就不展开说明了。 发布以后,可以登录npm官网: https://www.npmjs.com/ 查看一下你的包是否有成功发布。 现在搜索我刚刚发布的包的名字: 可以看到包已经成功发布了,版本为1.0.0