前言
前段时间看的爬虫都是不需要登录直接爬取数据,这回就试试爬取需要登录的网站信息吧,说干就干,直接就拿segmentfault做为目标!
一、爬虫所需模块
- superagent
- async
二、分析
我们首先用chrome或者其他浏览器打开segmentfault的主页,找到它的登录接口,点击登录接口,记得把Preserve log勾上,否则跳转之后找不到接口,如图(重要信息打了马赛克):
显而易见这是一个post请求,三个参数分别是用户名、密码、和是否记住密码的标记。
获取Cookie里的PHPSESSID
仔细看请求头header
里的cookie
,在请求发送的时候就已经有了,我们直接把整个请求头拿过来,就直接用图中的接口和header
登录,逐一删除cookie
中的项,测试登录结果,最终发现只有PHPSESSID
是必须的。这个PHPSESSID
如何获取呢?我们可以在登录之前先访问segmentfault
主页,将返回的cookie
拿到,再在登录的时候加上这个cookie
即可。
获取cookie的代码如下:
1 | (cb) => { |
获取Query String Paramsters里的 _ 参数
还有一个参数需要注意:接口中的Query String Paramsters
的_
参数,那么这个参数是怎么来的呢?在返回的response
的header
里寻找并没有找到它的踪迹,所以猜想它应该是隐藏在源码里,我们直接在chrome
控制台的source
下全局搜索_=
(source
顶部右键选择search in all files
即可出现全局搜索框),逐一排查可能性:
排查过程中发现箭头所指的ajaxSend
函数好像和我们需要的有关系:它紧邻的下面的delegate
函数内容应该就是登陆有关的内容,通过/api/user/?do=login
和submit
等就可以清楚的看出,这个函数中的url
是从n.attr('action')
拿到的,猜测这个n.__
肯定和请求中的Query String
参数脱不了关系。正好这个ajaxSend
函数中就有n.__
,也正好验证了我们刚才的推测,分析这行代码:1
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
中,如图:
找到来源就简单了,我们仍然是在登录直接先访问主页,将整个主页的html代码拿到,然后将这个script的内容取出来不就行了,哈哈,好开心~
获取script的代码如下:
1 | var cheerio = require('cheerio') |
到这里,登录就算完成了一大半了,接下来就是简单的用superagent
调用接口啦,这里的请求头出了cookie
的其他部分也是必须要设置的,可以直接从浏览器上copy下来,代码如下:
1 | (cb) => { |
终于返回200了,美滋滋,然后我们继续~比如我我想用代码修改个人主页的个人描述内容,首先我们先找到相关接口,如图:
这个post请求的参数description就是个人描述的所填写的新的内容,我们直接用superagent调用这个接口1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21(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/fighting123/node_login_segmentfault.git