做给自己用的命令行工具
最近自己用 Node 写了很多的小工具,然而并不能全局使用。上网找了下答案,发现了 TJ 大神写的 Commander.js 可以很方便的制作命令行工具。于是就照着 API 把之前的 知乎专栏爬虫 给整成 CLI 工具。我把工具命名为 nodc
,意思是node collection
,然而这一路并不平静,所以写下此文。
commander
: 命令行模块
这个模块是 TJ 大神封装好的模块,能快速开发命令行工具。官网有很多例子,我直接上我用到的方法。
1 |
|
上面是 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,幸好有中文版的,用了all
和after
两种方法。all
是全部事件触发emit
,就会执行执行。after
是在n
次执行完后,才触发,n
是after
的第二个参数。
按理说 for 循环用after
比较好处理,然而我拿不到 for 的次数,因为被封装在另一个函数中。我试了好多次都不成功。换all
吧,all
面临一个问题是,怎么样监听什么售后下载完,才发送给all
。由于我用的是request
模块的pipe
方法,后面不能监听呀。eventproxy
还没知道怎么用呢,两个方法都不能立马行得通,很打击人的啊。
认准一条路,脚踏实地的走下去
after
试过了很多次都行不通,all
又因为request
后面直接使用pipe
不能监听。果断选择all
,至少我知道只要能监听request
什么时候执行完,就可以发起all
了。而after
我根本就没有思路,就算这条路是捷径,我也走不了,还不如脚踏实地的 focus 目标。
既然request
直接使用pipe
不能监听,那我不直接使用不就行了。上网找了个 方法,用fs.writeStream
的on
监听。把eventproxy
的emit
放在on
callback 里面,用一个变量来累加计算,判断for
写入次数来执行emit
。
运行
因为我本来就没有 npmjs 的账号,所以不能发布在 npmjs 上,那怎么样全局使用呢?方法还是有的:
1 |
|
搞定。
还有很多事没做呢
这是只是我nodc
的第一个小功能,我还想集成更多
nodc
功能列表
- 知乎专栏爬虫
- 结巴分词全文排序关键词
- 天气预报
- 中英翻译
- …
而知乎专栏爬虫还有些问题需要解决:
- 文件名上加入文章发布时间,方便排序 (
20170717@learnreact.md
) - 代码还很不美观,而且部分代码需要重写,虽然可以运行(用
request
代替https
) - 增加 进度条,让爬虫进度更直观。
- 增加多 id 下载
- 输出带 颜色 的信息
你们可能会说,别人其实已经造好了很多轮子,比如翻译就有 ici,为什么我还要自己弄?因为别人的东西,如果出了 bug 🐛,我自己修改会很费力,或者我只能坐以待毙。而我想通过一个个小项目开源给大家一起来完善,自己享用自己的劳动成果,也是一件乐事。