正方教务系统爬虫实现
主要库
- requests,json,re
分析网页
第一眼就看到网页后缀是.aspx,也就是用的ASP.NET技术,不算老熟人有兴趣可以了解下https://baike.baidu.com/item/aspx/203251?fr=aladdin
登录网页称为网页1,随便输入一下账密fiddle抓一下,可以看到网页url,注意是POST
http://jw.dlust.edu.cn/default2.aspx
fiddle 抓登录界面
F12 里RadioButtonList1
重要参数__VIEWSTATE
也没加密,就一个__VIEWSTATE和RadioButtonList1这两个参数要注意一下,RadioButtonList1这个参数网上查了下,这个参数用的gb2312编码(正码就是“学生”),乱码不太清楚,看F12也是显示不出来,就剩下__VIEWSTATE。
在登录界面搜一下,网页源代码里就有这个参数的值
get获取__VIEWSTATE参数
现在需要思考一下,刚才fiddle的抓包可以看到是POST请求,表单数据要填写才能发送request。其实不然,post网页不一定要用post方法访问才能返回响应,通常query参数是GET请求时常用的携带参数方式。如果是POST请求也要携带query类型的参数,可以把它拼接到url里,至于能不能获取就看服务端。对应的get网页也不一定非要在url里传递参数,重要的是看服务器后台是如何解析的,网页请求的本质也就在于后台的解析,与get、post这些表面俗称的文字无太多区别只是人们定义的概念罢了。
网页1可以先使用get请求去获取到响应文本,应该是隔段时间每个ip访问的时候分配一个__VIEWSTATE数据和cookie一样,所以与填不填写表单并不重要,用的re,xpath当然也可都好用,结构化强的用xpath,数据简单易拿的用re。
注意对于这种登录网页一定要保持回话,re写个规则,header随便看看几个必要参数就可,而且第一次访问不需要cookie,直接get(url)就行,我们只要返回的文本和cookie
pattern1 = re.compile('__VIEWSTATE" value=\"(.*?)\"', re.S) # 获取vs
headeri = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","Accept-Encoding": "gzip, deflate","Accept-Language": "zh-CN,zh;q=0.9","Cookie": "","User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36","Referer": "http://jw.dlust.edu.cn/default2.aspx","Host": "jw.dlust.edu.cn","Cache-Control": "max-age=0"
}
# vs要经过两次更换,登录之间是vs1,登录后还要再获取一次vs2
vs = 0
# cookie要保持一直,不管是申请验证码还是模拟登录,都要一致,所以cookie变量用一次改一次
cookie = 0
def get_first_VS():global cookie, vsurl = "http://jw.dlust.edu.cn/default2.aspx"resp1 = s.get(url)text = resp1.text# 进去之前的 vs1vs = re.search(pattern1, text).group(1)cookie = dict(resp1.cookies)cookie = 'ASP.NET_SessionId=' + cookie['ASP.NET_SessionId']headeri['Cookie'] = cookieprint("============第一次get访问获取vs和cookie成功============\n进入之前的vs:{}\nCookie:{}".format(vs,cookie))
ok,现在我们已经有vs1(后面还有vs2,把登录界面的__VIEWSTATE参数称作vs1),和cookie了 。
验证码获取
不会机器学习,后期准备找个轮子先用着,现在就先把验证码图片保存下来手动输入吧
验证码的获取就比较简单了,就是个简单的GET请求,url如下
需要注意的是get请求要用第一步中的vs1,和cookie,其他的没啥了
http://jw.dlust.edu.cn/CheckCode.aspx
因为使用的session保持会话,所以没有加headers,但原理要理解
def get_yzm():url = 'http://jw.dlust.edu.cn/CheckCode.aspx'resp = s.get(url)with open('./yzm.jpg', 'wb') as f:f.write(resp.content)print("============获取验证码成功============")
进入系统
至此,POST请求所需的参数都已准备好,body参数,用@RequestBody注解注入(json数据注入到类的对象属性中)在requests.post表现为data参数,不要忘了解码下(“gb2312”),顺便拿一下学生的xh(学号),xm(姓名),后面有用
__VIEWSTATE | 第一次get访问得到的:vs1 |
txtUserName | 学号 |
TextBox2 | 密码 |
txtSecretCode | 手动输入验证码 |
RadioButtonList1 | %D1%A7%C9%FA(“学生”的gb2312编码) |
pattern2 = re.compile('<span id="xhxm">(.*?)同学',re.S) # 获取姓名
def join_system():un = input("学号:")pd = input("密码:")yzm = input("验证码:")data = {"__VIEWSTATE": vs,"txtUserName": un,"TextBox2": pd,"txtSecretCode": yzm,"RadioButtonList1": "%D1%A7%C9%FA", # 学生选项"Button1": "","lbLanguage": ""}ss = s.post(url='http://jw.dlust.edu.cn/default2.aspx', data=data, headers=headeri)# 保存会话很关键text = ss.content.decode('gb2312')if ss.status_code == 200:print("============进入系统成功==============")xh = untry:xm = re.search(pattern2,text).group(1)print("==========获取姓名学号成功=========\n姓名:{}\n学号:{}".format(xm,xh))except Exception as e:print("==========获取姓名学号失败=========")print(e)
运行后输出下text看有没有成功的信息,比如text中出现了自己的学号和姓名则表明进入系统成功
如果出现了Object moved to here.,典型的302跳转后面会详细说,referer参数修改下:
http://jw.dlust.edu.cn/xs_main.aspx?xh=自己的学号
获取成绩
点击查询成绩按钮fiddle抓的这个连接,进入后的系统页面称为网页2
http://jw.dlust.edu.cn/xscj.aspx?xh=学号&xm=姓名&gnmkdm=N121604
可以发现网页2的vs参数和网页1使用的不同,F12再看一下果然,vs不一样了,网页2的vs参数称为vs2
同理步骤
- get访问,拿到vs2
- 再用post,vs2当做参数
其他参数
xh,xm,Button2
xh就是你的账号(学号),xm和网页1参数中的RadioButtonList1很相似,盲猜是你姓名的gb2312编码呈乱码,Button2参数在body主体中,应该和vs2参数一样通过网页body主体获取,从F12元素获取中定位了该元素,value值为中文,可以大胆的猜测这个乱码同样是“在校学习成绩查询”的gb2312编码呈乱码。
为了验证,用fiddle replay重写参数再次访问观察返回结果,果然验证了我们的猜想成绩出来了。
gnmkdm,txtQSCJ,txtZZCJ
gnmkdm:发现个很有意思的事,很可能是网站搭建员懒这完全是中文缩写gnmkdm(功能模块代码),这个参数也就顾名思义的代表不同的模块的代码,在校学习成绩查询的代码就是N121601,当然还有别的模块这里不再说明,方法一样
txtQSCJ,txtZZCJ:和Button2那个一样是从body主体中获取的,对应的value值
关于Object moved to here
需要注意的是,post访问该url时http://jw.dlust.edu.cn/xscj.aspx?xh=学号&xm=姓名&gnmkdm=N121604,必须修改headers中的Referer参数,不然会出现Object moved to here,该问题的出现是网页在执行一个重定向操作,但并没有给出具体定向连接所以抛出了here。所以必须在post成绩url时加上referer参数,可以在fiddle中找到
获取成绩
至此所有参数已准备好
xh | 学号 |
xm | 姓名(直接写姓名就行,不用gb2312转码) |
gnmkdm | 不同的模块对应不同的代码,成绩的是N121604 |
__VIEWSTATE | 进入网页2get获取 |
txtQSCJ | 元素value值 |
txtZZCJ | 元素value值 |
Button2 | 同样是元素value值(中文就行,不用gb2312转码) |
pattern3 = re.compile('<tr class="alt">.*?'+'<td>(.*?)</td>.*?'+ # 课程编号'<td>(.*?)</td>.*?'+ # 课程名'<td>(.*?)</td>.*?'+ # 课程类型'<td>(.*?)</td>.*?'+ # 期末成绩'<td>(.*?)</td>.*?'+ # 总成绩'<td>.*?</td>.*?'+ # null'<td>.*?</td>.*?'+ # null'<td>.*?</td>.*?'+ # null'<td>(.*?)</td>.*?'+ # 学分'<td>.*?</td>.*?'+ # 辅助标记'</tr>',re.S)# 获取成绩
def get_score(xh,xm):url = 'http://jw.dlust.edu.cn/xscj.aspx' # xscj = ??成绩# querystring,用params,可以写在url后params = (("xh", 学号),("xm", 姓名),("gnmkdm", "N121604"), # gnmkdm功能模块代码,每个按钮对应的不一样,成绩查询是N121604)# print(header)resp = s.get(url,params=params, headers=headeri)if resp.status_code == 200:print("获取新 vs 成功!")text = resp.text# 进来后的 VStry:vs = re.search(pattern1, text).group(1)print("进去后的vs:", vs)except:print("获取进入后的vs失败,可能由于验证码输入错误,请重新开启系统")else:print("第一次访问(获取vs失败)")# 接收参数时,用@RequestBody注解注入,用datadata={"__VIEWSTATE": vs,"txtQSCJ": "0", # 学生选项"txtZZCJ": "100","Button2": "在校学习查询"}resp2 = s.post(url,params=params,data=data,headers=headeri)text2 = resp2.textform_table(text2)def form_table(text):# 包含成绩的列表score_list = re.findall(pattern3,text)for score_item in score_list:print(score_item)# print(score_list)
如果运行不成功,很可能是参数问题,仔细观察
拓展
试了下课表查询,还行。只要进来后基本上vs和cookie就不用再动了,用初始的session会话再加上相应的参数就可以畅通无阻,其实主要的两个功能就是查成绩和查课表。后期可以做个网站,查成绩就登陆(单向加密),只想看课表就游客只看课表就行。查课表的参数都在HTML代码里,常见的传value。有时间再写个模型,跑一下验证码不然自动不了。
正方教务系统爬虫实现相关推荐
- python实现高校教务管理系统_Python实现新版正方教务系统爬虫
目录~ 引入 需要什么软件? 模拟登陆 代码实现(登陆) 模拟获取成绩 代码实现(获取成绩) 解析成绩 测试(完成图) 作者的话 引入 就在我刚刚写完旧版正方系统爬虫的时候(旧版正方系统爬虫代码) 学 ...
- Python实现新版正方教务系统爬虫(二)
前言 哎对不起 我可能是silly boy 我想在学校里把去年的坑填了 但是发现新版的教务系统代码没传到git上 我现在就成了个对着空ide发呆的憨憨(代码在家里啦 所以填坑就再过会吧 那就稍微闲聊一 ...
- 广州商学院Python正方教务系统爬虫(获取个人信息成绩课表修改密码)
使用python的requests库简单爬取,使用xpath解析内容 可以获取个人信息.个人照片.成绩单和课表 github地址:https://github.com/PythonerKK/GZCC- ...
- 正方教务系统成绩爬虫的实现
正方教务系统爬虫 简介 一.设计思路以及工具 二.实现步骤 1.登陆流程 1.1抓取登陆链接 1.2 验证码获取 1.3 发送登陆请求 2.读入数据 2.1 获取历年成绩对应的__VIEWSTATE ...
- php模拟登陆青果教务系统,模拟登录 - php CURL模拟登陆正方教务系统
代码如下 $cookie_file = tempnam('./temp','cookie'); $login_url = 'http://211.64.47.129/default_ysdx.aspx ...
- python爬虫学校正方教务系统获取全部成绩
python爬虫正方教务系统许昌学院 来自许昌学院的大四小菜鸡,疫情封在宿舍,闲来无事在宿舍爬了一下之前没成功的教务系统爬虫,当时觉得挺难的,今天发现这个还是挺简单的,这个程序参考了很多前辈大佬们的程 ...
- 一个爬进正方教务系统的爬虫的诞生
我的新博客地址: http://jujuba.me/ 0x00. 准备工作 工具: chrome python 一些python库,主要是requests 要想爬进教务系统,首先要知道教务系统的网址 ...
- 我的第一个开源项目:Java爬虫爬取旧版正方教务系统课程表、成绩表
Java爬虫爬取旧版正方教务系统课程表.成绩表 一.项目展示 1.正方教务系统 首页 2.爬虫系统 首页: 成绩查询: 课表查询: 二.项目实现 1.爬取思路描述 无论是成绩查询或课表查询亦或者其它的 ...
- 拟物校园 | 拟物校园,一个高校教务系统爬虫,现支持正方教务、青果教务。
特别声明:除非注明,否则均为 夏末浅笑博客 原创文章,禁止任何形式转载 nivinEdu 拟物教务,一个高校教务系统爬虫 github:https://github.com/nivin-studio/ ...
最新文章
- struts启动时加载_iOS优化篇之App启动时间优化
- 跟我学jQuery(二) 初识jQuery
- idea 如何隐藏/展示不想看到的文件
- python def函数报错详解_JSer 快速入门 Python 之函数详解
- 第一个Spring冲刺周期团队进展报告
- .net 跳出Frameset框架
- Linux中的VMware共享文件夹
- 基于STM32开发板和Web网页的蔬菜大棚温湿度、光照等变化的动态柱形图表
- 基于ZFS+SAS的Tier2/backup存储系统解决方案
- ubuntu磁盘空间清理
- INF安装信息文件①
- Qt 中信号和槽机制
- 找不到设备 将计算机连接到USB打印机,打印机连接电脑没反应怎么办
- sql server中datetime默认值设置和日期函数
- python def 识别print_Python零基础快速入门(一):print()函数与变量
- 【报错解决】expected single matching bean but found 2
- java-php-python-ssm在线影视点播系统计算机毕业设计
- 始祖双碳新闻 | 2022年8月15日碳中和行业早知道
- NX二次开发-UFUN拉伸函数UF_MODL_create_extruded
- php 微擎 白屏,关于微擎安装模块后,打开空白页的处理方法
热门文章
- 干货:服务器网卡组技术原理与实践
- [Swift]LeetCode1031. 两个非重叠子数组的最大和 | Maximum Sum of Two Non-Overlapping Subarrays...
- 亚马逊影响者红人,用关联视频给卖家带来哪些好处?
- 精确度,召回率,真阳性,假阳性
- STM32-定时器输入捕获实验(捕获PWM方波的频率和占空比)
- 项目中分页查询得实现
- 互联网晚报 | 05月17日 星期二 | 郑州首套房贷利率最低降至4.4%;可口可乐被曝员工不得购买竞品...
- c++ socket发送string 、char*字符串,客户端接收到乱码
- 对路径“C:\”的访问被拒绝
- Vue 链接生成二维码