当前位置: 首页 > 后端技术 > Node.js

从零开始开发一个Node交互式命令行应用

时间:2023-04-03 15:36:42 Node.js

简介:对于大多数前端开发者来说,说到命令行工具,想必大家都用过。但是说到开发命令行工具,估计很少有人懂。本文旨在帮助大家在最短的时间内开发出一个实用的(眯着眼睛笑)图片爬虫命令行应用。如果你想追求更好的阅读体验,欢迎光临拓跋前端客栈。同时,将项目地址放在显眼位置。Puppeteer简介什么是Puppeteer?Puppeteer是GoogleChrome团队的官方无头Chrome工具。Chrome是浏览器市场的领导者,ChromeHeadless将成为网络应用自动化测试的行业标杆。所以我们有必要去了解它。Puppeteer可以做什么?Puppeteer可以做的事情很多,包括但不限于:利用网页生成PDF、抓取网站图片自动提交表单、UI测试、键盘输入等,帮助您创建一个最新的自动化测试环境(chrome),可以直接在此处运行测试用例捕获您站点的时间线以跟踪您的站点并帮助分析站点性能问题Puppeteer有哪些优势?与真正的浏览器相比,加载css、js和渲染页面的工作更少。无头浏览器比真正的浏览器快得多。可以在没有接口的服务器或CI上运行,减少了外界干扰,更加稳定。一台机器上可以模拟多个无头浏览器运行,方便并发操作。如何安装木偶师?安装Puppeteer很简单,如下:npmi--savepuppeteeraryarnaddpuppeteer需要注意的是,由于使用了ES7的async/await语法,所以node版本最好是v7.6.0以上。如何使用木偶师?由于本文不专门介绍Puppeteer,所以这部分暂时略过。大家可以去下面的链接学习。PuppeteerGithubPuppeteerApiDocPuppeteerChineseApiDoc说了那么多,Puppeteer跟我们要开发的命令行应用有什么关系呢?我们将制作一个用于捕获图像的命令行工具。我们没有使用传统的基于请求的爬虫,而是使用像Puppeteer这样的无头浏览器从DOM中捕获图像,可以有效地规避一些爬虫防御。Puppeteer简单应用案例1.截图直接上传代码,简单易懂:constpuppeteer=require("puppeteer");constgetScreenShot=async()=>{constbrowser=awaitpuppeteer.launch({headless:false});constpage=awaitbrowser.newPage();awaitpage.goto("https://baidu.com");awaitpage.screenshot({path:"baidu.png"});awaitbrowser.close();};getScreenShot();这段代码的意思是以无头(headless)模式打开浏览器,然后打开一个新的标签页,跳转到百度网站,并截图,保存为一张图片,命名为baidu.png,最后关闭浏览器。执行结果如下。案例2.抓取网站信息接下来学习如何使用Puppeteer抓取网站信息。这次我们来抓取京东图书列表信息。//书籍信息spiderconstpuppeteer=require("puppeteer");constfs=require("fs");constspider=async()=>{constbrowser=awaitpuppeteer.launch();constpage=awaitbrowser.newPage();awaitpage.goto("https://search.jd.com/Search?keyword=javascript");constresult=awaitpage.evaluate(()=>{letelements=document.querySelectorAll(".gl-item");constdata=[...elements].map(i=>{return{name:i.querySelector(".p-nameem").innerText,描述:i.querySelector(".p-namei").innerText,价格:i.querySelector(".p-price").innerText,商店:i.querySelector(".p-shopnum").innerText,url:i.querySelector(".p-imga").href};});returndata;//返回数据});浏览器.close();返回结果;};spider().then(value=>{fs.writeFile(`${__dirname}/javascript.json`,JSON.stringify(value),err=>{if(err){throwerr;}console.log("文件已保存!");});控制台e.log(值);//成功!});我们做的是跳转到关键字为javascript的页面,然后分析页面的dom结构,找到标题、描述、价格、发布者、网页链接信息,然后将数据写入javascript.json文件,这样我们就可以非常方便的保存浏览逻辑。这已经是一个爬虫的雏形了,最终得到下图所示的json文件,非常强大。案例三、图片爬虫图片爬虫,这是我们要做的命令行应用的主题。一个最基本的思路是这样的:打开浏览器—>跳转到百度图片—>获取输入框的焦点—>输入关键词—>点击搜索按钮—>跳转到结果列表页—>下拉到最底层—>操作dom获取所有图片的src进行备份—>根据src保存相应的图片到本地—>关闭浏览器代码实现:一、浏览器操作部分constbrowser=awaitpuppeteer。发射();//打开浏览器constpage=awaitbrowser.newPage();//打开新标签页awaitpage.goto("https://image.baidu.com");//跳转到百度图片console.log("gotohttps://image.baidu.com");//获取输入框的焦点awaitpage.focus("#kw");//将焦点定位在搜索输入框上awaitpage.keyboard.sendCharacter("cat");//输入关键字awaitpage.click(".s_search");//点击搜索按钮console.log("gotosearchlist");//提示跳转到搜索列表页,然后是图片处理部分page.on("load",async()=>{awaitautoScroll(page);//向下滚动加载图片console.log("pageloading完成,开始获取...");constsrcs=awaitpage.evaluate(()=>{constimages=document.querySelectorAll("img.main_img");returnArray.prototype.map.call(images,img=>img.src);});//获取所有img的srcconsole.log(`get${srcs.length}images,startdownload`);f或(leti=0;i","yourname","zhl").option("-a,--age<年龄>","你的年龄","22").option("-e,--enjoy[enjoy]").action(option=>{console.log('name:',option.name);console.log('age:',option.age);console.log('enjoy:',option.enjoy);});program.parse(process.argv);Commander非常易于使用。上面的代码只使用了几行来定义命令行的输入和输出。其中:version定义版本号description定义描述信息option定义输入选项,传递3个参数,如option("-n,--name","yourname","GK"),第一项是传递参数的值,-n是缩写形式,--name是全名形式,表示输入参数,<>是必填项,如果是[],就是一个可选项目。第二项“yourname”是求助时的提示信息,告诉用户输入什么,最后一项“GK”是默认值。action定义了要执行的动作,是一个回调函数。输入参数是上面输入的option选项。如果没有输入选项,将使用定义的默认值。查询更详细的api,请参考CommanderApi文档。执行上面的脚本,可以得到:这样命令行就可以实现简单的交互效果了。但是你觉得不够好看吗?别担心,继续阅读。使用inquirer制作交互式命令行应用程序Inquirer可以为Node.js制作一个可嵌入且美观的命令行界面。可提供问答命令输入:可提供多种形式的选择界面:可验证输入信息:最终可对输入信息进行处理:以上示例为查询器官方示例,可参考pizza的文档.jsinquirer查看inquirer文档有了inquirer,我们可以做出更优雅的交互式命令行工具。使用chalk.js让界面更美观chalk的语法非常简单:constchalk=require('chalk');constlog=console.log;//组合样式字符串和普通字符串blue.bgRed.bold('Helloworld!'));//传入多个参数log(chalk.blue('Hello','World!','Foo','bar','biz','baz'));//嵌套样式log(chalk.red('Hello',chalk.underline.bgBlue('world')+'!'));//嵌套相同类型的样式even(color,underline,background)log(chalk.green('我是一条绿线'+chalk.blue.underline.bold('带有蓝色子串')+'又变绿了!'));可以输出如下信息,一看就懂:letusdosomethinginteresting...肯定有人看到下面知乎的控制台效果了,既然我们想做点有趣的,今天不妨加上这个效果给命令行程序改进风格。首先,我们准备一对用于打印的ASCII码。可以自行搜索文本转ASCII。网上没有太多转换方案。我们要制作的命令行图片蜘蛛,会制作一个IMGSPD的ASCII字符串~选择后效果如图:这么复杂的字符串怎么打印出来?直接存成字符串肯定不行,格式会乱。如果你想把格式完整地打印出来,有一个技巧就是以注释的形式打印出来。什么可以保存评论?~~函数。所以事情就像打印一个函数一样简单。但是直接打印函数还是不够的。这时候我们就用到了可以用到天上的toString()方法。我们只需要将评论的中间部分用正则表达式进行匹配即可。Easy~最后看一下效果,铛铛铛铛~支持双击运行。这里使用了一种叫做Shebang的技术。Shebang(也称为Hashbang)是由#和!组成的hashbang。由字符序列#!,它显示为文本文件第一行的前两个字符。在文件中存在Shebang的情况下,类Unix操作系统的程序加载器会解析Shebang之后的内容,将该内容作为解释器指令调用该指令,并使用包含该Shebang的文件路径Shebang作为解释器参数。在node下,我们可以使用#!/usr/bin/envnode。这个时候我们可以取消文件的扩展名。js。添加环境变量,支持全局调用配置package.json中的"bin":{"img-spd":"app"},执行npmlink,会将img-spd字段复制到npm的全局模块安装文件夹node_modules中,并创建符号链接(symboliclink,软链接),即将app的路径添加到环境变量PATH中。这时候在任意目录下,直接在命令行输入img-spd运行这个命令行,感觉满满的幸福感都快溢出来了。最后用动图展示一下:附录项目地址项目地址Installnpminstall-gimg-spdUsageimg-spdorUsage:img-spd[options]img-spd是一个spidergetimagesfromimage。baidu.comOptions:-v--version输出版本号-k,--key[key]输入图片关键字下载-i,--interval[interval]输入操作间隔(ms,default200)-n,--number[number]输入运行间隔(ms,default200)-m,--headless[headless]选择程序是否以无头模式运行-h,--help输出使用信息