在sf回答完一个问题后,总有一个优先操作,就是取消关注这个问题,因为当你回答完一个问题后,系统默认你关注了这个问题。这对于有点强迫症的我来说是一种困扰,因为这样一来,别人回答这个问题的时候,系统就会提醒一次。当一个问题火了,很多人来回答的时候,这些提醒就太尴尬了。在sf里,我提倡的attention是automaticattention,passiveattention等等,我不要。废话这么多,于是想到了写一个脚本来收集问题的关注度和回答数之间的关系。猜猜,这种被动关注真的有必要吗?或者,我看看有没有人回答过和我一样的问题,然后取消了关注。。。其实这种数据收集最好有数据库,但是,我们不是公司的员工sf...思路是先在首页获取所有问题(貌似显示80),但不是所有问题都有答案,所以根据上一步获取的链接过滤出问题链接,访问问题详情页一个一个收集主要数据(问题标题、链接、收藏数、回答数、关注数、浏览数)记录过滤上一步收集的主要数据(这里过滤,我主要看回答数+1>关注数,提问者默认关注问题本身)使用nightmare,需要安装。它基于electron,安装过程可能需要python2。Nightmare主要是promise格式写的代码,所以我封装了一个函数,方便后续编程//url是页面链接//evaluate是页面内嵌的js运行函数//thenCbk是node作用域下的后续回调函数,并且参数接收evaluate函数返回的内容){console.error('nightPagefailed!url:',url,'\nerror:',error);});}//closenightmarefunctionend(message){console.log('ending:'+message);nightmare.end().then(function(res){console.log('nightmareend!');//this是后面处理数据调用staticLog();});}所以页面数据的收集和后续处理依赖于evalute和thenCbk的逻辑。首先访问首页获取问题链接合集:varres=[];[].forEach.call(questions,function(questionWrap,index){varanswer=questionWrap.querySelector('.answers');varurl;//在问题dom中,有几个答案回答类表示是回答if(/\bananswered\b/.test(answer.className)){url=window.location.protocol+'//'+window.location.host+questionWrap.querySelector('.summary.titlea').getAttribute('href');res.push(url);}});returnres;},function(questions){//这里使用全局变量保存链接,主要是为了方便后面的遍历问题和访问页面gQuestions=questions;analyzeQuestion();});}得到问题集后,thenCbk下一步就是调用analyzeQuestion函数analyzeQuestion(){varurl;//该方法主要是递归调用,终止条件为//全局变量gQuestions中的元素个数为0时终止if(gQuestions.length){url=gQuestions.pop();//访问问题页面详情nightPage(url,function(){//这是js内嵌的页面,所以不能访问node作用域下的变量,所以不能共享一些方便计算的工具函数//页面数据简写为`1.3k`class对数据进行转换(不过好像没什么用,主要是浏览号里会有这样的数据)functiontransformNum(str){if(/k/.test(str)){returnparseFloat(str)*1000;}return+str;}//标题、回答数、粉丝数、收藏数、浏览量varobj={};//#questionTitlea获取标题和链接vartitle=document.querySelector('#questionTitlea');obj.title=title.textContent;obj.url=title.getAttribute('href');//.widget-answers文章获取答案数varanswers=document.querySelectorAll('.widget-answersarticle');obj.answer=answers.length;//.post-topheader__sidestrong获取粉丝数和浏览量vartopHeader=document.querySelector('.post-topheader__side');obj.follow=transformNum(topHeader.querySelector('强').textContent);obj.read=transformNum(topHeader.querySelector('.no-stress').textContent);//#sideBookmarked获取收藏数量varmark=document.querySelector('#sideBookmarked');obj.mark=transformNum(mark.textContent);//.post-topheader__side.no-stress//返回采集到的数据returnobj;},functioncollectDetail(detail){//将数据推送到另一个全局变量markLog数组tomarkLog.push(detail);console.log(url,'collected');//递归调用analyzeQuestion();});}else{//调用完成后,end('windowending');}}写到这里,数据收集就完成了,剩下的就是比较过滤数据了我的筛选就像我之前描述的比较一样简单。functionsummaryLog(){varallAnswer=0,allFollow=0,allMark=0;fLtA=[];//关注人数<回答人数+1提问自动跟随markLog.forEach(function(log){allAnswer+=log.answer;allFollow+=log.follow;allMark+=log.mark;if(log.follow
