当前位置: 首页 > Web前端 > HTML

写一个CLI工具抓取奇物周刊文章链接

时间:2023-03-28 17:52:29 HTML

介绍前端er应该都知道奇物周刊,它是一个聚集了大量优秀博主贡献的技术文章的技术博客。以上文章我个人都是隔几天看一次,但是官网经常打不开,每次想看文章都得一页一页翻,才能找到想看的文章。或者,有时候只是想找一篇文章看看,作为知识的扩展或者复习。基于阅读文章方便的考虑,开始了对这个CLI工具的探索。这个工具的核心功能是从开发者的角度快速找到奇物周刊上发表文章的链接。主要功能是抓取所有文章链接,随机N篇文章链接,定时任务自动抓取所有文章链接。该功能的作用是抓取文章链接数据,为CLI工具开发提供数据支持,为后续开发提供关键词检索和文章开发。内容爬取、文章推荐等功能铺垫。npx75_actionfetcharticledatalocalcache作为命令行工具时,从官网抓取数据的过程会消耗20s+的时间,所以使用本地文件来缓存抓取的文章数据。npx75_actionrandom命令执行后,会自动缓存并抓取数据到本地,缓存的有效期为24h。随机N篇文章链接CLI工具的主要功能之一,运行命令随机返回N篇文章的数据。npx75_actionrandom定时任务自动抓取使用GithubActions配置定时任务,每天08:00执行自定义执行[[#拼全文章链接]]任务,抓取文章数据上传到GitHub即可下载。文章数据的方案设计与获取CLI工具缓存策略功能实现文章数据抓取对应的源码可以在这里查看:https://github.com/JohnieXu/7...抓取奇物周刊官方首页的HTML网站并解析出文章集合数据functiongetCollections(){returnfetch(homeUrl).then(res=>res.text()).then(res=>{if(!res){returnPromise.reject(newError('获取网页内容失败'))}returncheerio.load(res)}).then($=>{constlist=$('ol.issue-list>li')constcollections=list.map((i,l)=>{consttitle=$(l).find('a').attr('title')consturl=$(l).find('a').attr('href')constdate=$(l).find('.date').attr('datetime')return{title,url,date}})returncollections})}抓取collectionURL页面的HTML并解析出文章数据集合函数下getArticleDoc(url){returnfetch(homeUrl+url).then(res=>res.text()).then(res=>{if(!res){returnPromise.reject(newError("Failedtogetwebcontent"))}returncheerio.load(res)})}functiongetArticles(doc){const$=docconstel=$('ul>li.article')constlist=el.map((我,l)=>{return{title:$(l).find('h3.title>a').text(),url:$(l).find('h3.title>a').attr('href'),desc:$(l).find('.desc').text()}})returnlist}整合文章数据并排序输出getArticleDoc(url).then(getArticles).then(list=>list.map((_,item)=>({...item,issue:title,date}))).then(list=>{all=[...all,...list]})//整合文章数据all=all.sort((a,b)=>b.date.localeCompare(a.date))//date文章的日期字段倒序就是对应的发布日期(期刊日期)集合,例如:2021-12-17,需要对日期进行倒序排序,使用String.prototype.localeCompare()进行字符串排序文章数据缓存对应的源码可以在这里查看:https://github.com/JohnieXu/7...缓存文件和有效期constCACHE_FILE='./.75_action/.data.json'constCACHE_TIME=1000*60*60*24;//cache24hconsthomeDir=require('os').homedir()constp=path.resolve(homeDir,CACHE_FILE)//缓存文件路径读取用户主目录下缓存文件的修改时间判断是否已过期(不存在缓存文件也视为缓存过期){returntrue}conststat=fs.statSync(p)constlastModified=stat.mtimeconstnow=newDate()returnnow-lastModified>=CACHE_TIME}如果没有过期,读取缓存文件作为抓取文章数据函数getHomeFileJson(){consthomeDir=require('os').homedir()constp=path.resolve(homeDir,CACHE_FILE)constjsonStr=fs.readFileSync(p)让json尝试{json=JSON.parse(jsonStr)}catch(e){console.error(e)json=[]}returnjson}抓取文章数据写入本地缓存函数writeFileToHome(json){consthomeDir=require('os').homedir()constp=path.resolve(homeDir,CACHE_FILE)//写入路径是用户的主目录returnmkdirp(path.dirname(p)).then(()=>{fs.writeFileSync(p,JSON.stringify(json,null,2))//以JSON格式序列化})}CLI工具开发配置bin入口运行npx75_action命令,使用Node.js执行这里指向的75_action.js脚本查看:https://github.com/JohnieXu/7...命令行参数使用commander库来注册CLI命令并解析命令参数constprogram=require('commander')//注册命令program.command('random[number]').description('获取n个随机文章链接').option('-d,--debug','启用调试模式').action((number,options)=>{number=number||1if(options.debug){console.log(number,options)}fetch({save:'home',progress:true}).then(({collections,articles})=>{constselected=random(number,articles)console.log(JSON.stringify(selected,null,2))process.exit()}).catch((e)=>{console.log(e)process.exit(1)})})program.command('fetch').description('重新获取文章链接').option('-d,--debug','启用调试模式').action((options)=>{if(options.debug){console.log(options)}fetch({save:'home',progress:true,reload:true}).then(({collections,articles})=>{console.log(`fetch完成,一共${collections.length}collections,${articles.length}articles`)process.exit()})})program.parse(process.argv)命令行进度条使用cli-progress库实现命令行进度条效果constcliProgress=require('cli-progress')constbar1=newcliProgress.SingleBar({},cliProgress.Presets.shades_classic)bar1.start(collections.length,0)//文章收藏数量设置为总数progressvaluebar1.update(doneLen)//在捕获任何文章集合后更新进度条。该功能使用GitHubActions自动执行计划任务。在项目中添加对应的yml配置文件即可。对应源码在这里查看:https://github.com/JohnieXu/7...name:FETCHon:push:branches:-masterschedule:-cron:"00,8,16***"#Executeat0816每天(有8小时时差)jobs:build:runs-on:ubuntu-lateststrategy:matrix:node-version:[16.x]#在https://nodejs.org/en/about/releases/查看支持的Node.js发布计划步骤:-uses:actions/checkout@v2-name:UseNode.js${{matrix.node-version}}使用:actions/setup-node@v2with:node-version:${{matrix.node-version}}cache:'npm'-run:npmi-gyarn-run:yarn-run:nodeindex.js-name:saveuses:actions/upload-artifact@v2with:path:data.json使用actions/checkout克隆仓库源码,使用actions/setup-node来切换节点。js版本为16.X,最后使用actions/upload-artifact打包输出执行nodeindex.js命令生成的data.json文件上传到github执行效果npmpackagerelease确保本项目支持执行命令npx75_action,需要添加这个项目发布到npm官方仓库,项目名称为75_action。发布流程如下(部分命令根据实际情况选择),nrm的用法可以在这里查看:https://www.npmjs.com/package...。nrmusenpm#将npm源切换为官方npmlogin#登录npm账号npmrunpublish#发布成品以下命令均在终端执行,要求Node.js版本至少为10.X及以上,终端中的node和npx命令可用Normaluserandomonearticlenpx75_actionrandomrandom5articlesnpx75_actionrandom5randomNarticles(N为正整数)npx75_actionrandomN获取并更新本地文章datanpx75_actionfetch奇物周刊文章标题、描述和文章原始链接的CLI工具。该工具在Node.js上执行。基本满足了快速获取奇物周刊文章链接的需求。同时文章数据也可以缓存到本地,有效提升用户体验。另外还有一些高级功能没有开发,比如:根据文章标题进行关键词搜索,返回最新文章合集,根据文章标题分类,文章有效性检测链接等。以上未开发的功能将视情况陆续开发,欢迎关注本项目后续进展。项目地址在这里:https://github.com/JohnieXu/7...。参考资料[1]String.prototype.localeCompare():https://developer.mozilla.org...[2]cheerio文档:https://github.com/cheeriojs/...[3]指挥官使用文档:https://github.com/tj/command...[4]cli-progress使用文档:https://github.com/npkgz/cli-...[5]GitHubActions使用教程:https://docs.github.com/cn/ac...