前段时间看的爬虫都是不须要登陆直接爬取数据,这回就试试爬取须要登陆的网站信息吧,说干就干,直接就拿segmentfault作为目标!html
咱们首先用chrome或者其余浏览器打开segmentfault的主页,找到它的登陆接口,点击登陆接口,记得把Preserve log勾上,不然跳转以后找不到接口,如图(重要信息打了马赛克):node
显而易见这是一个post请求,三个参数分别是用户名、密码、和是否记住密码的标记。git
仔细看请求头header
里的cookie
,在请求发送的时候就已经有了,咱们直接把整个请求头拿过来,就直接用图中的接口和header
登陆,逐一删除cookie
中的项,测试登陆结果,最终发现只有PHPSESSID
是必须的。这个PHPSESSID
如何获取呢?咱们能够在登陆以前先访问segmentfault
主页,将返回的cookie
拿到,再在登陆的时候加上这个cookie
便可。
获取cookie的代码以下:github
(cb) => { superagent .get('https://segmentfault.com') .end((err, res) => { if (err) console.log(err) cookie = res.headers['set-cookie'].join(',').split(';')[0] // 获取PHPSESSID cb(null) }) }
还有一个参数须要注意:接口中的Query String Paramsters
的_
参数,那么这个参数是怎么来的呢?在返回的response
的header
里寻找并无找到它的踪影,因此猜测它应该是隐藏在源码里,咱们直接在chrome
控制台的source
下全局搜索_=
(source
顶部右键选择search in all files
便可出现全局搜索框),逐一排查可能性:ajax
排查过程当中发现箭头所指的ajaxSend
函数好像和咱们须要的有关系:它紧邻的下面的delegate
函数内容应该就是登录有关的内容,经过/api/user/?do=login
和submit
等就能够清楚的看出,这个函数中的url
是从n.attr('action')
拿到的,猜想这个n.__
确定和请求中的Query String
参数脱不了关系。正好这个ajaxSend
函数中就有n.__
,也正好验证了咱们刚才的推测,分析这行代码:chrome
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
中找了生成它的代码,包含在一个script
中,如图:segmentfault
找到来源就简单了,咱们仍然是在登陆直接先访问主页,将整个主页的html代码拿到,而后将这个script的内容取出来不就好了,哈哈,好开心~
获取script的代码以下:api
var cheerio = require('cheerio') function getRandom(s) { let $ = cheerio.load(s) let script = $('script').eq(8).html() let fn = new Function('window', script + ';return window.SF.token') let token = fn({}) $ = null return token } exports.getRandom = getRandom
到这里,登陆就算完成了一大半了,接下来就是简单的用superagent
调用接口啦,这里的请求头出了cookie
的其余部分也是必需要设置的,能够直接从浏览器上copy下来,代码以下:浏览器
(cb) => { const username = process.argv[2] const password = process.argv[3] console.log(cookie) console.log(random) let header = { 'accept': '*/*', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9', 'content-length': '47', 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 'cookie': `PHPSESSID=${cookie};`, 'origin': 'https://segmentfault.com', 'referer': 'https://segmentfault.com/', 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/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了,美滋滋,而后咱们继续~好比我我想用代码修改我的主页的我的描述内容,首先咱们先找到相关接口,如图:cookie
这个post请求的参数description就是我的描述的所填写的新的内容,咱们直接用superagent调用这个接口
(cb) => { superagent // 编辑右上角我的说明 .post('https://segmentfault.com/api/user/homepage/description/edit') .query({'_': random}) .set(header) .type('form') .send({ description: '努力coding的小喵~~~' }) .end((err, res) => { if(err) throw err let result = JSON.parse(res.text) if (result.status === 0) { console.log('编辑成功') } else { console.log('编辑失败:' + result.data) } }) cb(null, 1) }
返回状态码200,而后直接去浏览上的主页刷新下,能够看到我的描述的内容已经成功更新了!
segmentfault
主页并登录,找到登陆请求的接口并分析node
登陆以前,先请求主页接口,目的是拿到PHPSESSID
和源代码中的生成Query String
的函数整个登陆过程耗费了好久的时间,有空就研究这个Query String
的来源,好不容易登陆成功想干点事情,又没注意到设置请求头,觉得是sf_remember
参数的问题,又折腾了许久,还好,最终总算是成功了!感谢本身的不放弃~
github地址:https://github.com/fighting12...