Cookie模拟登录(免验证码)
概述
Cookie指某些网站为了辨明用户身份、进行session(会话)跟踪而储存在用户本地终端上的数据。辨明身份,自然要保存用户的的相关信息了,所以可以通过Cookie来模拟登录网站。
获取Cookie信息
- 进入ZUCC选课网,打开开发者工具里面的Network选项
- 输入账号、密码、验证码(这里输入验证码是为了获取Cookie,以后用Cookie登录就无需验证码了)
- 找到“default2.aspx”文件——“Headers”里面的“Request Headers”,复制里面的Cookie
- 请求头里加入Cookie信息即可登录
1
2
3
4
5
6
7
8
9
10
11import requests
url = 'http://xk.zucc.edu.cn/default2.aspx'
headers = {
'Cookie': 'ASP.NET_SessionId=XXXXXXX; AntiLeech=XXXXXXX',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
}
html = requests.get(url, headers=headers)
print(html.text)
POST方法登录(手动验证码 + OCR自动验证码)
Cookie由于各种原因,大概率无效,尝试POST表单交互
分析
查看表单的网页源代码,确定提交方式是POST
观察表单源码中input标签,获取表单提交字段
逆向工程(抓包)确认表单的提交字段
(1)进入ZUCC选课网,打开chrome开发者工具,选择network选项
(2)手动输入账号和密码后登录
(3)在“default2.aspx”的文件中,“From Data”里面就是需要提交的字段1
2
3
4
5
6
7
8
9
10__VIEWSTATE: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
txtUserName: XXXXXXXX
Textbox1:
TextBox2: XXXXXXXX
txtSecretCode: 4cx1
RadioButtonList1: (unable to decode value)
Button1:
lbLanguage:
hidPdrs:
hidsc:__VIEWSTATE: 相传这个是.Net框架特有产物,会变化,在html源码的form标签下的第一个hidden的input标签里可以看到值
1
<input type="hidden" name="__VIEWSTATE" value="dDwxNTMxMDk5Mzc0Ozs+HjPJ2APgB+73zYSyRsZkjFxlx0A=">
txtUserName: 学号参数
Textbox1: 用来实现记住密码的功能的(讲道理chrome的记住密码比这个功能好用多了)
TextBox2: 用来传输密码的(抓包的时候看到,密码没有一点点加密,直接明文传送)
txtSecretCode: 验证码
RadioButtonList1: 通过view source查看源码,可以看到1
2__VIEWSTATE=dDwxNTMxMDk5Mzc0Ozs%2BHjPJ2APgB%2B73zYSyRsZkjFxlx0A%3D&txtUserName=XXXXXXXX
&Textbox1=&TextBox2=XXXXXXXX&txtSecretCode=tkx7&RadioButtonList1=%D1%A7%C9%FA&Button1=&lbLanguage=&hidPdrs=&hidsc=- 其中”RadioButtonList1=%D1%A7%C9%FA”可以推断出来,代表为学生。用URL反编译出来,也确实是汉字“学生”
审查元素,验证码地址是“CheckCode.aspx”
基本思路
- 开启session,先抓取教务系统首页
- 再单独抓取一次验证码(即人类登录时看不清换一张验证码的功能)
- download验证码,显示给人类/OCR
- 人类填写验证码/OCR识别验证码
- 构造登录数据,post数据登录
代码实现
获取账号信息
1 | def get_information(): |
初始化登录爬虫
1 | class LoginSpider: |
访问首页
获取__VIEWSTATE的值,并抓取验证码到本地
1 | def hello_world(self): |
1 | def down_code(self): |
每提交一次选课,VIEWSTATE就会更新一次。所以后面会一直用到获取VIEWSTATE的信息,直接封装成一个函数
1 | def get_view_state(response): |
登录状态判断
定义一个判断是否成功登录的函数。对于登录成功和登录失败的页面,用etree解析页面,xpath定位title。根据title的不同就可以判断
1 | def login_status(response): |
手动打码登录
1 | def login_manual(self): |
OCR识别验证码登录
1 | def login_ocr(self): |
完整代码
Cookie登录功能已经废弃,OCR代码识别代码参见OCR验证码识别(Python)
1 | import json |