正方教务系统成绩爬虫的实现

简介

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

一、设计思路以及工具

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

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

二、实现步骤

1.登陆流程

1.1抓取登陆链接

首先爬虫的登陆不同于常规的网页登陆,需要找到登陆请求的post连接,所以需要使用检查-NetWork抓包,建议开启Preserve log,这样会显示所有登陆时产生的网络交互信息。
1.1设置检查
首先在登陆界面输入一次错误信息,可以捕获到请求发送的目标地址
1.2抓取登陆请求
可以看到在登陆请求中有四个重要字段包含在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是个隐藏状态的输入框。
1.3ViewState获取
通过以下代码可以将它提取出来

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

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

1.2 验证码获取

通过观察页面的Element,可知验证码图片是从CheckCode.aspx文件下获取到的
1.4验证码获取来源分析
由此我们可以知道需要通过get方法去得到验证码,在观察了请求头后,发现只有cookie比较特殊,我们可以知道,验证码匹配就是用的Cookie中的ASP.NET_SessionId作为依据。
1.5 验证码获取
所以我们需要从登陆请求页面获取到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

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

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

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

其中的xh对应学号,xm对应姓名(需要从页面提取,或者从用户输入)
但是如果直接访问是会出现以下界面的
在这里插入图片描述
这说明我们无法直接使用原来的请求头获取页面
在观察这个请求的结构时,发现__VIEWSTATE已经不是原来那个了
在这里插入图片描述
于是为了获取这个最新的页面我们需要先GET方法获取页面源代码,从中取得__VIEWSTATE的值,然后再次POST过去。

	    #使用get请求先get到__VIEWSTATE
	    rln = 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 存放数据

    #初始化工作环境使用Xlwt
    workbook = xlwt.Workbook(encoding = 'utf-8')
    #表名
    worksheet = workbook.add_sheet('Score')
    #行数,列数初始化
    row = 0
    column = 0
    for tr in soup.find_all('tr'):
        row = row+ 1
        column = 0
        for 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文档

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
新版正方教务系统 SDK for Python(新正方教务系统API),自动识别验证码(包含两种验证码的处理 爬虫(Web Crawler)是一种自动化程序,用于从互联网上收集信息。其主要功能是访问网页、提取数据并存储,以便后续分析或展示。爬虫通常由搜索引擎、数据挖掘工具、监测系统等应用于网络数据抓取的场景。 爬虫的工作流程包括以下几个关键步骤: URL收集: 爬虫从一个或多个初始URL开始,递归或迭代地发现新的URL,构建一个URL队列。这些URL可以通过链接分析、站点地图、搜索引擎等方式获取。 请求网页: 爬虫使用HTTP或其他协议向目标URL发起请求,获取网页的HTML内容。这通常通过HTTP请求库实现,如Python中的Requests库。 解析内容: 爬虫对获取的HTML进行解析,提取有用的信息。常用的解析工具有正则表达式、XPath、Beautiful Soup等。这些工具帮助爬虫定位和提取目标数据,如文本、图片、链接等。 数据存储: 爬虫将提取的数据存储到数据库、文件或其他存储介质中,以备后续分析或展示。常用的存储形式包括关系型数据库、NoSQL数据库、JSON文件等。 遵守规则: 为避免对网站造成过大负担或触发反爬虫机制,爬虫需要遵守网站的robots.txt协议,限制访问频率和深度,并模拟人类访问行为,如设置User-Agent。 反爬虫应对: 由于爬虫的存在,一些网站采取了反爬虫措施,如验证码、IP封锁等。爬虫工程师需要设计相应的策略来应对这些挑战。 爬虫在各个领域都有广泛的应用,包括搜索引擎索引、数据挖掘、价格监测、新闻聚合等。然而,使用爬虫需要遵守法律和伦理规范,尊重网站的使用政策,并确保对被访问网站的服务器负责。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值