前言前段时间看的爬虫是不登录直接爬取的,这次我们来尝试爬取需要登录的网站信息,就这么干吧,以segmentfault为目标!一、爬虫需要的模块superagentasync二、分析我们先用chrome或者其他浏览器打开segmentfault的首页,找到它的登录界面,点击登录界面,记得勾选Preserve日志,不然找不到界面跳转后,如图(重要信息是马赛克):很明显这是一个post请求,三个参数分别是用户名,密码,是否记住密码。获取cookie中的PHPSESSID仔细看请求头中的cookie,在发送请求的时候就已经存在了,我们直接拿整个请求头,直接用图中的界面和头登录,删掉cookie中一项一项,测试登录结果,最后发现只需要PHPSESSID。如何获得这个PHPSESSID?我们可以在登录前访问segmentfault主页,获取返回的cookie,然后在登录时添加这个cookie。获取cookie的代码如下:(cb)=>{superagent.get('https://segmentfault.com').end((err,res)=>{if(err)console.log(err)cookie=res.headers['set-cookie'].join(',').split(';')[0]//获取PHPSESSIDcb(null)})}获取QueryStringParamsters中的_参数是不是又需要一个参数注:接口中QueryStringParamsters的_参数,那么这个参数是怎么来的呢?在返回的response的header中搜索也没有找到它的踪迹,所以猜测应该是隐藏在源码中,我们直接在chromeconsole的源码下全局搜索_=(在源码上方右击选择搜索inallfilestoappearGlobalsearchbox),一一检查可能性:在检查过程中,发现箭头所指的ajaxSend函数似乎与我们需要的相关:旁边的delegate函数的内容应该和登录相关,通过/api/user/?do=login和submit可以清楚的看到这个函数中的url是从n.attr('action')中获取的,猜测n.__一定和request中的QueryString参数密不可分。正好在这个ajaxSend函数中有n.__,正好验证了我们刚才的推测。分析这行代码:n.url.indexOf("?")===-1?n.url=n.url+"?_="+i._:n.url=n.url+"&_="+i._n.url默认为n.url+"?_="+i._,那么这个i.__应该就是最终boss了。在这个文件中找到定义i的代码,如上图箭头所示,继续全局搜索SF.token,最后在index.html中找到生成它的代码,包含在一个脚本中,如下如图:找源很容易。我们还是先登录访问首页,获取整个首页的html代码,然后取出脚本内容。哈哈,太开心了~获取脚本的代码如下:varcheerio=require('cheerio')functiongetRandom(s){let$=cheerio.load(s)letscript=$('script').eq(8).html()letfn=newFunction('window',script+';returnwindow.SF.token')lettoken=fn({})$=nullreturntoken}exports.getRandom=getRandom在这点,即使登录完成了一大半,接下来就是简单的用superagent调用接口,这里的请求头中必须设置cookie的其他部分,直接从浏览器复制即可,代码如下:(cb)=>{constusername=process.argv[2]constpassword=process.argv[3]console.log(cookie)console.log(random)letheader={'accept':'*/*','accept-encoding':'gzip,deflate,br','accept-language':'zh-CN,zh;q=0.9','con帐篷长度':'47','内容类型':'application/x-www-form-urlencoded;charset=UTF-8','cookie':`PHPSESSID=${cookie};`,'origin':'https://segmentfault.com','referer':'https://segmentfault.com/','user-agent':'Mozilla/5.0(WindowsNT6.1;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/65.0.3325.181Safari/537.36','x-requested-with':'XMLHttpRequest'}superagent.post(`https://segmentfault.com/api/user/login`).query({'_':random}).set(header).type('form').send({username:username,password:password,remember:1}).end(function(err,res){if(err){console.log(err.status);}else{console.log('返回状态码:'+res.status)cb(null)}})},终于返回200,开心,然后我们继续~像我一样想用代码修改个人主页的个人描述内容。首先我们先找到相关的接口,如图:本次发帖请求的参数描述为个人描述中填写的新内容。我们直接用superagent(cb)=>{superagent调用这个接口//编辑右上角的个人描述。post('https://segmentfault.com/api/user/homepage/description/edit').query({'_':random}).set(header).type('form').send({description:'努力码字的小喵~~~'}).end((err,res)=>{if(err)throwerrletresult=JSON.parse(res.text)if(result.status===0){console.log('editedsuccessful')}else{console.log('editedfailed:'+result.data)}})cb(null,1)}返回状态码200,然后直接走到浏览器首页刷新,可以看到个人介绍的内容已经更新成功!综上所述,打开segmentfault主页并登录,找到登录请求接口,分析一下。使用node登录前,先请求首页接口。目的是通过这两个参数获取PHPSESSID和源码中生成QueryString的函数来请求登录界面。请记住设置请求标头。登录成功后,你可以做任何你想做的事情。整个登录过程耗时很长。如果你有时间,研究一下这个查询字符串的来源。登录成功后,你想做点什么,但你没有注意到设置。对于requestheader,我以为是sf_remember参数的问题,纠结了半天。幸运的是,它终于成功了!感谢不放弃~源码github地址:https://github.com/fighting12...