正方教务系统爬虫

  • 简介
  • 一、设计思路以及工具
  • 二、实现步骤
    • 1.登陆流程
      • 1.1抓取登陆链接
      • 1.2 验证码获取
      • 1.3 发送登陆请求
    • 2.读入数据
      • 2.1 获取历年成绩对应的__VIEWSTATE
    • 3.数据处理
      • 3.1 存放数据
  • 总结

简介

这是利用python爬虫对正方教务系统成绩进行爬取,将爬取到的成绩放入excel中的程序。

一、设计思路以及工具

正方教务系统主要使用了ASP.NET技术,是一个比较好的爬虫练手程序。

PythonIDE:Anaconda
使用库:requests_html,bs4,requests,xlwt,os

二、实现步骤

1.登陆流程

1.1抓取登陆链接

首先爬虫的登陆不同于常规的网页登陆,需要找到登陆请求的post连接,所以需要使用检查-NetWork抓包,建议开启Preserve log,这样会显示所有登陆时产生的网络交互信息。

首先在登陆界面输入一次错误信息,可以捕获到请求发送的目标地址

可以看到在登陆请求中有四个重要字段包含在data中
txtUserName:登陆用户名
TextBox2:密码
txtSecretCode:验证码
__VIEWSTATE:

ViewState是
http://ASP.NET中用来保存WEB控件回传时状态值一种机制。在WEB窗体(FORM)的设置为runat=”server”,这个窗体(FORM)会被附加一个隐藏的属性_VIEWSTATE。_VIEWSTATE中存放了所有控件在ViewState中的状态值。

ViewState是类Control中的一个域,其他所有控件通过继承Control来获得了ViewState功能。它的类型是system.Web.UI.StateBag,一个名称/值的对象集合。

当请求某个页面时, http://ASP.NET把所有控件的状态序列化成一个字符串,然后做为窗体的隐藏属性送到客户端。当客户端把页面回传时,
http://ASP.NET分析回传的窗体属性,并赋给控件对应的值。

这个东西是不可或缺的,而我们又怎么找到它呢?
实际上,在页面的结构中我们就能找到它,它存在与input的value中,这个input是个隐藏状态的输入框。

通过以下代码可以将它提取出来

    #   使用BeautifulSoup进行页面处理,提取出__VIEWSTATEsoup = BeautifulSoup(res.text,'lxml')     viewState = soup.find('input', attrs={'name': '__VIEWSTATE'})['value']

由此我们可知我们将要将用户名,密码,验证码,VIEWSTATE以数据的形式发送到"http://XXXXXXX/default2.aspx"

1.2 验证码获取

通过观察页面的Element,可知验证码图片是从CheckCode.aspx文件下获取到的

由此我们可以知道需要通过get方法去得到验证码,在观察了请求头后,发现只有cookie比较特殊,我们可以知道,验证码匹配就是用的Cookie中的ASP.NET_SessionId作为依据。

所以我们需要从登陆请求页面获取到Cookie

    #   cookie进行处理Cookie=str(res.cookies)[27:69]

并且将它放到请求头里

    headeri = {"Accept": "image/avif,image/webp,image/apng,image/*,*/*;q=0.8","Accept-Encoding": "gzip, deflate","Accept-Language": "zh-CN,zh;q=0.9","Cookie": 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://替换成你的jwxt网址/default2.aspx","Host": "替换成你的jwxt网址","Cache-Control": "max-age=0"}

发送请求保存图片,并要求用户进行验证(此处可以尝试用图像分析解决)

    #发送请求resi = session.get("http://XXXXX/CheckCode.aspx",headers=headeri,stream=True)#如果验证码文件已经存在则删除它,如果不存在就直接创建一个将验证码放入其中if os.path.exists(r'F://FzscoreGet//yanzheng.jpg'):os.remove(r'F://FzscoreGet//yanzheng.jpg')with open(r'F://FzscoreGet//yanzheng.jpg','wb')as f:f.write(resi.content)#打开验证码文件要求用户进行验证(待完善,目标自动识别)os.startfile(r'F://FzscoreGet//yanzheng.jpg')checkCode = input("请输入弹出的验证码:")

1.3 发送登陆请求

要求用户输入账号密码
初始化登陆数据

    login_info = {"__VIEWSTATE": viewState,"txtUserName": user, "TextBox2": pwd,"txtSecretCode": checkCode,"RadioButtonList1": "%D1%A7%C9%FA",#学生选项"Button1": "","lbLanguage": ""}

初始化请求头,此处cookie一定要和获取验证码的相同

    #处理登陆请求的请求头header = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Encoding": "gzip, deflate","Cookie": Cookie,"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8","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://替换成你的jwxt网址/default2.aspx","Host": "替换成你的jwxt网址","Origin":"替换成你的jwxt网址","Cache-Control": "max-age=0"
}

发送登陆请求

requests.session().post(url='http://xxxx/default2.aspx', data=login_info, headers=header)

2.读入数据

2.1 获取历年成绩对应的__VIEWSTATE

如果没有出现报错说明你已经成功登陆,在登陆后我们需要找到历年成绩的入口


访问历年成绩的页面的地址是这个

> 'http://jwxt.yxnu.edu.cn/xscjcx.aspx?xh={}&xm={}&gnmkdm=N121605'

其中的xh对应学号,xm对应姓名(需要从页面提取,或者从用户输入)
但是如果直接访问是会出现以下界面的

这说明我们无法直接使用原来的请求头获取页面
在观察这个请求的结构时,发现__VIEWSTATE已经不是原来那个了

于是为了获取这个最新的页面我们需要先GET方法获取页面源代码,从中取得__VIEWSTATE的值,然后再次POST过去。

     #使用get请求先get到__VIEWSTATErln = session.get('http://xxxxxxx/xscjcx.aspx?xh={}&xm={}&gnmkdm=N121605'.format(xh,name),headers=header)#错误处理,如果报错则说明验证码或账户密码错误,不细化分析错误,学有余力可以自己搞下  soup=BeautifulSoup(rln.text,'lxml')value3=soup.find('input', attrs={'name': '__VIEWSTATE'})['value']

把这个最新的__VIEWSTATE放入data中

    data={'btn_zcj':'%C0%FA%C4%EA%B3%C9%BC%A8',#学年成绩:btn_xn 历年成绩:btn_zcj'ddlXN':'','ddlXQ':'','__EVENTVALIDATION': '','__EVENTTARGET':'',   '__EVENTARGUMENT' :'','__VIEWSTATE':'','hidLanguage':'','ddl_kcxz':'',}data['__VIEWSTATE']=value3

并将其放入链接post出去

        #post请求获取到显示界面lncj = session.post('http://xxxx/xscjcx.aspx?xh={}&xm={}&gnmkdm=N121605'.format(xh,name),data=data,headers=header)soup=BeautifulSoup(lncj.text,'lxml')

此时soup中就已经是历年成绩了

3.数据处理

通过对soup的观察我们可以知道成绩存放在form表格中,通过form的分析我们可以知道一个<tr>标签下有若干个<td>,由此我们可以使用循环获取。

3.1 存放数据

    #初始化工作环境使用Xlwtworkbook = xlwt.Workbook(encoding = 'utf-8')#表名worksheet = workbook.add_sheet('Score')#行数,列数初始化row = 0column = 0for tr in soup.find_all('tr'):row = row+ 1column = 0for td in tr.find_all('td'):worksheet.write(row,column, label = str(td.get_text()))column=column+1#保存excel    workbook.save('Score.xls')

总结

以上,就是一次爬取正方教务系统历年成绩的实现过程,总体来说是不难的,只是在验证码获取方面我卡了很久。爬取过程还可以继续完善,这只是实现的思路而不是完整的程序。实现过程中其实发现有一个地方可以挖坑,就是验证码,验证码功能可以尝试直接识别而不用用户输入。

最后感谢学校和正方教务系统提供的练手机会。

参考文章:http://ddrv.cn/a/288264ython 爬虫案例——正方教务学生成绩获取
参考文档:BeautifulSoup文档

正方教务系统成绩爬虫的实现相关推荐

  1. 正方教务系统换数据库服务器,附:正方教务系统成绩录入操作说明- 正方教务系统成绩管理使用说明.doc...

    附:正方教务系统成绩录入操作说明- 正方教务系统成绩管理使用说明 正方教务系统成绩录入操作说明 正方教务系统成绩管理包括成绩录入.统计分析.成绩单回收确认和查询打印几项功能,其中成绩录入包括后台成绩录 ...

  2. 一个爬进正方教务系统的爬虫的诞生

    我的新博客地址: http://jujuba.me/  0x00. 准备工作 工具: chrome python 一些python库,主要是requests 要想爬进教务系统,首先要知道教务系统的网址 ...

  3. 新版正方教务系统Java爬取_正方教务系统成绩爬取(仅个人)+tk可视化

    [JavaScript] 纯文本查看 复制代码var CryptoJS = CryptoJS || function (u, p) { var d = {}, l = d.lib = {}, s = ...

  4. python爬虫学校正方教务系统获取全部成绩

    python爬虫正方教务系统许昌学院 来自许昌学院的大四小菜鸡,疫情封在宿舍,闲来无事在宿舍爬了一下之前没成功的教务系统爬虫,当时觉得挺难的,今天发现这个还是挺简单的,这个程序参考了很多前辈大佬们的程 ...

  5. 我的第一个开源项目:Java爬虫爬取旧版正方教务系统课程表、成绩表

    Java爬虫爬取旧版正方教务系统课程表.成绩表 一.项目展示 1.正方教务系统 首页 2.爬虫系统 首页: 成绩查询: 课表查询: 二.项目实现 1.爬取思路描述 无论是成绩查询或课表查询亦或者其它的 ...

  6. 广州商学院Python正方教务系统爬虫(获取个人信息成绩课表修改密码)

    使用python的requests库简单爬取,使用xpath解析内容 可以获取个人信息.个人照片.成绩单和课表 github地址:https://github.com/PythonerKK/GZCC- ...

  7. python实现高校教务管理系统_Python实现新版正方教务系统爬虫

    目录~ 引入 需要什么软件? 模拟登陆 代码实现(登陆) 模拟获取成绩 代码实现(获取成绩) 解析成绩 测试(完成图) 作者的话 引入 就在我刚刚写完旧版正方系统爬虫的时候(旧版正方系统爬虫代码) 学 ...

  8. Python实现新版正方教务系统爬虫(二)

    前言 哎对不起 我可能是silly boy 我想在学校里把去年的坑填了 但是发现新版的教务系统代码没传到git上 我现在就成了个对着空ide发呆的憨憨(代码在家里啦 所以填坑就再过会吧 那就稍微闲聊一 ...

  9. python提前查成绩_Python爬虫案例——正方教务学生成绩获取(自动识别验证码)...

    刚刚进入假期,学校开放了期末成绩查询,奈何正方教务的各种卡顿.很多学弟学妹问有没有好办法能够解决,闲来无事写了一段自动获取的爬虫程序练练手. 环境Python3.7 Jupyter 主要库reques ...

最新文章

  1. leetcode 30. Substring with Concatenation of All Words 与所有单词相关联的字串 滑动窗口法
  2. 开源贡献 计算_如何克服恐惧并为开源做贡献
  3. CodeForces - 867E Buy Low Sell High (贪心 +小顶堆)
  4. jQuery中实现全选功能时使用attr( )改变checked值只能生效一次的问题
  5. B Convex Polygon
  6. spring-test的简单实用方式
  7. linux ssh注册码,linux ssh -l 命令运用
  8. Android设计模式之——责任链模式
  9. 转:短小强悍的JavaScript异步调用库
  10. indesign用于产品排班_2019年机器人行业十大新品盘点,过去一年最受关注的产品都在这...
  11. Qt_Error QObject: Cannot create children for a parent that is in a different thread. 线程注意!!!
  12. 远程接入--为什么选择异速联
  13. Hiho1384 倍增+归并排序
  14. antd组件:Table表格去掉表格边框线,#字类型表格
  15. leetcode LCP 03. 机器人大冒险 -java
  16. 伽卡他卡学生端卸载方案
  17. vue引入 wps在线编辑版
  18. WEB相关:Windows下打造完美的服务器平台
  19. 教你怎样维持异地恋!
  20. linux桌面文件夹路径是什么,【已解决】Ubuntu中右键(桌面和文件夹)打开终端(定位到当前路径)...

热门文章

  1. springboot+redis实现登录失败次数限制
  2. DL之RefineNet:RefineNet和Light-Weight RefineNet算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
  3. mermaid制作饼图
  4. 天啦,从Mongo到ClickHouse我到底经历了什么?
  5. 服务器开虚拟机总是gpu满载,vSphere 环境机器学习 GPU 加速方案选型
  6. 【C51单片机】交通红绿灯设计(仿真)
  7. linux嵌入式红绿灯,嵌入式上机课设(红绿灯)..doc
  8. Elasticsearch 文档内容检索插件 ingest attachment 安装
  9. wordpress友联_wordpress怎么添加友情链接
  10. c语言中调用函数fn,C语言常见的函数调用