继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

使用Node.js做出自己的CLI工具

布宝
关注TA
已关注
手记 22
粉丝 9581
获赞 319

最近自己用 Node 写了很多的小工具,然而并不能全局使用。上网找了下答案,发现了 TJ 大神写的 Commander.js 可以很方便的制作命令行工具。于是就照着 API 把之前的 知乎专栏爬虫 给整成 CLI 工具。我把工具命名为nodc,意思是node collection。除了知乎专栏爬虫,我还把中央天气预报加到里面。以后有用空还会加入跟多的小工具。

commander: 命令行模块

这个模块是TJ大神封装好的模块,能快速开发命令行工具。官网有很多例子,我直接上我用到的方法。

#!/usr/bin/env node

var program = require('commander');
require('shelljs/global');
var zhihu = require("./src/zhihu.js")
var weather = require("./src/weather.js")

program
    .command('crawler [zhihuId]')
    .alias('cr')
    .description(' 知乎专栏爬虫 ')
    .option('-o ,--out <path>'," 输出位置")
    .action(function(zhihuId, options){
        var zhihuId = zhihuId || "leanreact";
        var path =  options.out || process.cwd();//当前执行路径
        console.log('   知乎专栏爬取 %s 到 %s 文件夹',zhihuId, path);
        zhihu(zhihuId,path)
    }).on('--help', function() {
    console.log('  举个栗子:');
    console.log();
    console.log('    $ nodc crawler leanreact');
    console.log('    $ nodc cr leanreact -o ~/');
    console.log();
  });

program
    .command('weather [townName]')
    .alias('wt')
    .description(' 天气助手 ')
    .option('-d ,--detail'," 输出位置")
    .action(function(townName, program){
        var townName = townName || "深圳";
        // var d =  program.detail || false;//当前执行路径
        // console.log('   知乎专栏爬取 %s 到 %s 文件夹',townName, path);
        weather(townName,program)
    }).on('--help', function() {
    console.log('  举个栗子:');
    console.log();
    console.log('    $ nodc crawler leanreact');
    console.log('    $ nodc cr leanreact -o ~/');
    console.log();
  });

program
    .parse(process.argv);

上面是 commander 模块创建类似git一样的子命令的代码

command:是创建子命令的方法,可以接收两个参数。接收一个参数时,可以使用 action 方法在后面发起动作。接收两个参数时,第二个参数是命令说明,后边就不能使用action了。[zhihuId]意思是可选参数,因为我后面在action方法里设置了默认知乎专栏id

alias:子命令别名

description:命令摘要说明

option:子命令属性。我设置了输出路径属性,接收两个参数,第二个参数为命令说明。字符串中-o必须在--out前面,后面<path>是必填参数。如果option不跟在command后面,则作为主命令的属性。

action:动作,顾名思义,就是发起子命令时做什么动作。传一个匿名函数做参数,前面 command 后面括号的内容可以作为参数传入。而 option 的中括号的参数需要用options.参数来传入

on:这里设置了help的说明

.parse(process.argv):没了这个代码好像不能用,这个放在所有 program 的最后,就像是 JavaScript程序的return,放在这行代码后面的commander 模块代码都不会执行,就算只是简单打console.log也不会执行。不过我在前面调用了zhihu(zhihuId,path)zhihu()里面的代码引用并不受它影响。

关于这个模块就说这么多。更多用法可以去github看README,有中文版的。

整合 GetZhiHuZhuanLan

之前写这个爬虫留下了很多问题没处理,这也是我参考zhangolve的项目的后遗症。第一个问题是,把整个爬虫分成两部分处理的:爬取下载,线下处理。第二个问题是,代码转换都成单行。由于这段时间都没空,也就搁置了。前些天看到 Node也能写命令行工具,就拿这个爬虫来试手。翻出来看,完全不能忍啊。于是找各种办法把问题处理了。

把两个分离模块合在同一个文件里

其实不写成同一个文件里也没关系的。不过为了开发方便,不用切换文件,我还是硬把两个模块的所有代码都放进去了。放进去,改了下参数名跑了一次,卧槽,线下处理的for循环居然跑在爬取下载模块的前面,怪不得之前我参考的项目是把两个文件分开来执行。

怎么办?怎么办?这问题很让人抓狂啊。

这时候一定要冷静,两个模块能分开运行,都能完成自己的任务,问题处在哪里?问题在于JavaScript的任务队列里:线下处理模块是被 for 包裹的同步运行代码,而爬取下载是一个异步的任务。如果把两个模块放一起,异步任务发起后,执行异步需要时间,而这时候,轮到for循环,它要处理下载好的json文件,可是异步下载还没完成呢,自然for里面的任务就异常了。

首次使用 eventproxy

相同了这个问题,赶紧去恶补 callback ,异步的知识,用了 async,感觉要搞很多代码,转向用朴灵大神的eventproxy。其实这个我完全是第一次玩呀,硬着头皮上吧。

看了下 README,幸好有中文版的,用了allafter两种方法。all是全部事件触发emit,就会执行执行。after是在n次执行完后,才触发,nafter的第二个参数。

按理说for循环用after比较好处理,然而我拿不到for的次数,因为被封装在另一个函数中。我试了好多次都不成功。换all吧,all面临一个问题是,怎么样监听什么售后下载完,才发送给all。由于我用的是request模块的pipe方法,后面不能监听呀。eventproxy还没知道怎么用呢,两个方法都不能立马行得通,很打击人的啊。

认准一条路,脚踏实地的走下去

after试过了很多次都行不通,all又因为request后面直接使用pipe不能监听。果断选择all,至少我知道只要能监听request什么时候执行完,就可以发起all了。而after我根本就没有思路,就算这条路是捷径,我也走不了,还不如脚踏实地的focus目标。

既然request直接使用pipe不能监听,那我不直接使用不就行了。上网找了个方法,用fs.writeStreamon监听。把eventproxyemit放在oncallback里面,用一个变量来累加计算,判断for写入次数来执行emit

中央气象预报

这个脚本还是比较容易实现的,在这里谢谢吴广海兄弟,帮我优化了代码。为了显示好看一点,我使用了cli-table2表格模块,在知乎爬虫和天气预报里都使用了Emoji。

运行与使用

因为我本来就没有npmjs的账号,所以不能发布在npmjs上,那怎么样全局使用呢?方法还是有的:

# 获取源码
$ git clone https://github.com/bubao/nodc
# 修改 index.js 第一行,换成自己 node 运行路径

# 项目的根目录下
$ sudo npm i -g

全部操作都在下面了:

# 查看帮助
$ nodc -h
# 知乎爬虫完整子命令
$ nodc cr [zhihuzhuanlanId] -o <path> 
# 默认路径为当前文件夹下
$ nodc cr [zhihuzhuanlanId]
# 默认只爬取 learnreact 专栏
$ nodc cr
# 天气预报完整子命令
$ nodc wt [townName] -d
# 天气基本信息
$ nodc wt [townName]
# 默认深圳天气
$ nodc wt 

知乎专栏爬虫

这个项目其实还有很多小 bug,code标签转换成 markdown 时是单反引号。目前的 markdown 转换工具使用的是 h2m ,如果有更好的工具请告知我,让我能尽快完善这个小爬虫,谢谢。

中央天气预报

这个项目用了-API 提供的 api 写的天气查询,目前还不是很完善,但是已经可以用了,后续继续做些小细节上的工作。

还有很多事没做呢

这是只是我nodc的第一个小功能,我还想集成更多。

nodc 功能列表

  • [x] 知乎专栏爬虫
  • [x] 中央天气预报
  • [ ] 结巴分词全文排序关键词
  • [ ] 彩色输出
  • [ ] 翻译
  • [ ] 纪念日提醒
  • [ ] 每日小tag
  • [ ] ...

而知乎专栏爬虫还有些问题需要解决:

  • [x] 文件名上加入文章发布时间,方便排序(20170717@learnreact.md)
  • [ ] 代码还很不美观,而且部分代码需要重写,虽然可以运行(用 request 代替 https)
  • [ ] 增加进度条,让爬虫进度更直观。
  • [ ] 增加多id下载
  • [ ] 输出带颜色的信息
说在最后的话

你们可能会说,别人其实已经造好了很多轮子,比如翻译就有 ici,为什么我还要自己弄?因为别人的东西,如果出了bug ,我自己修改会很费力,或者我只能坐以待毙。而我想通过一个个小项目开源给大家一起来完善,自己享用自己的劳动成果,也是一件乐事。

我希望这个小项目能更多的人参与进来,一起DIY自己的命令行工具集。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP