关于使用Python爬虫爬取教务网络管理系统的学生成绩,实际上博主在几个月前上课期间就已经写好了。记得当时是因为嫌查成绩麻烦懒得登录网页、恰好又学习了Python爬虫所以萌发了运行代码一键爬成绩的想法(我真是个小机灵鬼x懒是人类进步的根源)。接下来我先记录、分析一下当时爬取教务网络管理系统所遇到的问题,然后展示我所编写的代码。

思路分析

由于时间间隔较长,我就不再进行详细的爬取分析了。总体上来说,郑州轻工业大学教务网络管理系统使用的是青果教务网络管理系统的模板,只要了解了青果教务网络管理系统的源代码构造后,完成网络爬虫的爬取简直是轻而易举。同样的,不管是哪所高校,只要使用了青果教务网络管理系统,依葫芦画瓢就能进行爬虫的编写。
        因为青果教务网络管理系统作为一家普遍应用于全国各大高校的教务网络管理系统,自然具备着一定的反爬虫能力。所以一般的requests模块爬取还是有一定问题的。因此,这里我们主要使用的是Selenium自动化测试,及在网络爬虫被称之为“可见即可爬”的强大模块。由于时间问题(其实是懒),我就不进行函数封装了(博主在简单的代码编写中习惯先写好代码然后再封装为函数)。接下来,我们来说说分析的主要步骤:

1.我们想要进入教务网络管理系统页面,自首当其冲的目标是解决登录问题。那么我们打开郑州轻工业大学的教务网络管理系统官网的“开发者工具”进行分析。观察登录模块的整体源代码,可以发现我们要解决的第一个问题:Frame子页面问题。因为账号登录的整个模块是囊括在Frame子页面中,所以直接获取输入框和按钮是获取不到的。这时,我们可以通过以下代码解决:

browser.switch_to.frame('frm_login')   # 进入教务网的子Frame页面


        2.进入到教务网络管理系统的Frame子页面后,我们就可以直接获取到输入框和按钮了。关于账号和密码的输入,可以通过三种方式:① 直接写死到send_keys里面输入;② input()方法手动输入;③ 通过读取文件输入。这三种方式我都试过,最后是通过读入文件输入的(下列代码演示是通过input()方法输入)。

login = input("请输入账号: ")
password = input("请输入密码: ")
browser.find_element_by_id('txt_asmcdefsddsd').send_keys(login)
browser.find_element_by_id('txt_asmcdefsddsd').send_keys(Keys.TAB)   # TAB键是制表符,输入完账号后按下TAB跳至下一行密码输入框
browser.find_element_by_id('txt_pewerwedsdfsdff').send_keys(password)
browser.find_element_by_id('txt_sdertfgsadscxcadsads').click()   # 点击验证码框使验证码显示出来

如果需要读入文件输入,这里我使用的是txt文本。文本名称为“账号密码.txt”,文本内格式为账号和密码分别单独占一行。读取账号密码txt文本的代码如下所示:

with open('账号密码.txt', 'r') as file:   # 账号和密码分别为一行user = file.readlines()   # 读取账号密码到列表中login = user[0].strip()   # 账号password = user[1].strip()   # 密码

3.验证码问题。关于验证码的问题,我使用过python的OCR库进行了灰度化和二值化,但是识别效果很不理想(毕竟验证码的目的就是为了限制爬虫,属于反爬虫的手段之一)。所以,这里我使用Python的PIL库进行页面的整体截图+精细裁剪获取验证码并自动弹出。

# 验证码截图获取
image_file = "验证码.png"
screenshot = browser.save_screenshot(image_file)   # 获取屏幕截图,保存成验证码.png
wait = WebDriverWait(browser, 20)   # 显式等待最长20秒
img = wait.until(EC.presence_of_element_located((By.ID, 'txt_sdertfgsadscxcadsads')))   # 定位图片位置
time.sleep(1)
location = img.location
size = img.size
top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width']
# print("验证码位置:", top, bottom, left, right)   # 366 463 236 432
im = Image.open(image_file)
im = im.crop((left+210, top+275, right+206, bottom+280))   # 有头模式验证码位置
# im = im.crop((left+130, top+125, right+90, bottom+130))   # 无头模式验证码位置
im.save(image_file)   # 保存截取后的图片
im.show(image_file)   # 显示图片code = input("请输入识别后的验证码: ")
browser.find_element_by_id('txt_sdertfgsadscxcadsads').send_keys(code)
browser.find_element_by_id('btn_login').click()

4.输入验证码登录成功后,这里有些细节需要注意了!因为在多次尝试后,我发现在教务网络管理系统登录时如果之前登录的cookies生命周期还未消亡,此时登录会弹出“上次登录已下线”的弹窗。这里,我们通过一个if语句判断、捕获一下可能出现的弹窗问题。

# 判断是否出现弹窗,如果出现则进行捕获并点击确认
if browser.switch_to.alert:get_window = browser.switch_to.alert   # 捕获弹窗“您在别处的登录已下线”time.sleep(1)get_window.accept()   # 点击确认按钮
print("登录成功,现在您已到达郑州轻工业大学教务网络页面!")

5.打开开发者工具中的Network,点击“学生成绩”下的“查看成绩”选项,观察到新增加了Stu_MyScore.aspx,这里我们点击找到Request URL。这样,我们登录后只需请求该url就能够获取网页源代码并进行成绩的爬取。

6.接下来就没什么好说的,不过就是通过Selenium进行页面元素的获取完成爬虫。唯一需要注意的是青果教务网络管理系统的学生成绩不是文字的,因此不能直接进行爬取。这里我们通过selenium的屏幕截图代码直接截图解决。

browser.save_screenshot()

代码展示

from selenium import webdriver
import time
# import requests
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select   # 下拉选择框
# import tesserocr
from PIL import Imagewith open('账号密码.txt', 'r') as file:   # 账号和密码分别为一行user = file.readlines()   # 读取账号密码到列表中login = user[0].strip()   # 账号password = user[1].strip()   # 密码
# chrome_options = webdriver.ChromeOptions()
# chrome_options.add_argument('--headless')
# browser = webdriver.Chrome(options=chrome_options)   # 开启无头模式
browser = webdriver.Chrome()
# browser = webdriver.PhantomJS(executable_path=r'D:\PhantomJS\phantomjs-2.1.1-windows\phantomjs-2.1.1-windows\bin\PhantomJS')
browser.get('http://jiaowu.zzuli.edu.cn/jwweb/home.aspx')
time.sleep(2)   # 延时等待Frame子页面加载
browser.switch_to.frame('frm_login')   # 进入教务网的子Frame页面# login = input("请输入账号: ")
# password = input("请输入密码: ")
browser.find_element_by_id('txt_asmcdefsddsd').send_keys(login)
browser.find_element_by_id('txt_asmcdefsddsd').send_keys(Keys.TAB)   # TAB键是制表符,输入完账号后按下TAB跳至下一行密码输入框
browser.find_element_by_id('txt_pewerwedsdfsdff').send_keys(password)
browser.find_element_by_id('txt_sdertfgsadscxcadsads').click()   # 点击验证码框使验证码显示出来# 验证码截图获取
image_file = "验证码.png"
screenshot = browser.save_screenshot(image_file)   # 获取屏幕截图,保存成验证码.png
wait = WebDriverWait(browser, 20)   # 显式等待最长20秒
img = wait.until(EC.presence_of_element_located((By.ID, 'txt_sdertfgsadscxcadsads')))   # 定位图片位置
time.sleep(1)
location = img.location
size = img.size
top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width']
# print("验证码位置:", top, bottom, left, right)   # 366 463 236 432
im = Image.open(image_file)
im = im.crop((left+210, top+275, right+206, bottom+280))   # 有头模式验证码位置
# im = im.crop((left+130, top+125, right+90, bottom+130))   # 无头模式验证码位置
im.save(image_file)   # 保存截取后的图片
im.show(image_file)   # 显示图片print("欢迎来到郑州轻工业大学教务系统登录页面!")
code = input("请输入识别后的验证码: ")
browser.find_element_by_id('txt_sdertfgsadscxcadsads').send_keys(code)
browser.find_element_by_id('btn_login').click()
time.sleep(1)
# 判断是否出现弹窗,如果出现则进行捕获并点击确认
if browser.switch_to.alert:get_window = browser.switch_to.alert   # 捕获弹窗“您在别处的登录已下线”time.sleep(1)get_window.accept()   # 点击确认按钮
print("登录成功,现在您已到达郑州轻工业大学教务网络页面!")
# time.sleep(10)
# browser.close()browser.get('http://jiaowu.zzuli.edu.cn/jwweb/xscj/Stu_MyScore.aspx')   # 学生成绩里面的ajax地址
time.sleep(2)browser.find_element_by_id('SelXNXQ_2').click()   # 点击学期
cj = Select(browser.find_element_by_id('sel_xn'))
year = input("请输入学年:(例如2019-2020学年输入2019)\n")
cj.select_by_value(year)
xq = Select(browser.find_element_by_id('sel_xq'))
xueqi_input = input("请输入学期:(第一学期输入1/第二学期输入2)")
xueqi = str(int(xueqi_input)-1)
xq.select_by_value(xueqi)
cjlx = input("请输入成绩类型:(原始/有效)\n")
if cjlx == "原始":browser.find_element_by_id("ys_sj").click()   # 点击原始成绩browser.find_element_by_name("btn_search").click()   # 点击检索time.sleep(5)browser.save_screenshot(str(year) + "-" + str(int(year)+1) + '学年第' + xueqi_input + '学期原始成绩.png')
elif cjlx == "有效":browser.find_element_by_id("yx_sj").click()  # 点击有效成绩browser.find_element_by_name("btn_search").click()  # 点击检索time.sleep(5)browser.save_screenshot(str(year) + "-" + str(int(year) + 1) + '学年第' + xueqi_input + '学期有效成绩.png')
print("提示: 用户[" + login + "]在" + year + "-" + str(int(year)+1) + "学年第" + xueqi_input + "学期的" + cjlx + "成绩查询成功!")
browser.close()

运行效果展示


总结

第一次写这篇博客时我写的很详细、写了好多字,但是没想到发布后竟然丢了一大半!心态崩了啊!这个二周目我就不写那么多了,勉强我觉得还可以。
        因为时间原因(其实是懒),我未发布无头模式的教务网络管理系统爬虫。有头模式和无头模式的爬虫区别主要就在于验证码位置和成绩截图位置的问题,因为我只是为了图个乐呵、因此对于无头模式的成绩页面打开是缩放的问题没有解决。感兴趣的小伙伴可以根据我发布的有头模式的代码进行一定的扩展延伸,修改成无头模式并添加其他功能。

【Python网络爬虫实战篇】关于在青果教务网络管理系统爬取学生成绩的分析及代码展示——以郑州轻工业大学(zzuli)教务网络管理系统为例相关推荐

  1. 【python实现网络爬虫(4)】实习僧网站信息爬取(字体反爬虫破解)

    实习僧网站 实习僧网址,地址为北京,在搜索框输入"python",如下 实战解析 步骤一.建立for循环爬取前20页的内容 首先.查看翻页URL的信息,找规律 第一页:https: ...

  2. 爬虫实战(二)—利用requests、selenium爬取王者官网、王者营地APP数据及pymongo详解

    概述 可关注微信订阅号 loak 查看实际效果. 代码已托管github,地址为:https://github.com/luozhengszj/LOLGokSpider ,包括了项目的所有代码. 本文 ...

  3. Python高级特性与网络爬虫(二):使用Selenium自动化测试工具爬取一号店商品信息

    上一篇介绍了Ajax动态渲染的页面的分析和爬取,通过JavaScript动态渲染的页面的方式不只有ajax这一种,还有很多其他的方式,分析他们的网页结构和加密参数难度非常大,为了解决这样的页面的数据爬 ...

  4. 【Python网络爬虫实战篇】使用selenium+requests爬取下载高清源视频:关于爬取m3u8文件链接解析为ts视频合并成mp4视频的分析实战

    这两天博主在摸鱼时,偶然间接触到了流媒体的概念,一时间来了兴致.再加上之前博主有着七.八年的视频制作经验,深知视频素材获取的不易.因此,打算利用自己所学的python网络爬虫的知识,通过编写代码实现获 ...

  5. python如何全网爬取_如何爬取全网1200本Python书|爬虫实战篇

    这是菜鸟学Python的第98篇原创文章 阅读本文大概需要3分钟 引用 前面写了一篇文章关于爬取市面上所有的Python书思路,这也算是我们数据分析系列讲座里面的一个小的实战项目.上次代码没有写完,正 ...

  6. 【Java网络爬虫实战篇】使用Jsoup爬取和解析王者荣耀全英雄全皮肤(思路/代码/问题分析)

    由于博主前两天刚入门Java爬虫,并且自学了Jsoup的爬取和解析方式以及输入输出流的相关知识,因此打算检验一下目前的学习成果.在一番深思熟虑(x)后,毅然打算爬取王者荣耀官网全英雄全皮肤的壁纸. 爬 ...

  7. Python爬虫实战,Request+urllib模块,批量下载爬取飙歌榜所有音乐文件

    前言 今天给大家介绍的是Python爬取飙歌榜所有音频数据并保存本地,在这里给需要的小伙伴们代码,并且给出一点小心得. 首先是爬取之前应该尽可能伪装成浏览器而不被识别出来是爬虫,基本的是加请求头,但是 ...

  8. python爬取去哪儿网_python网络爬虫(12)去哪网酒店信息爬取

    目的意义 爬取某地的酒店价格信息,示例使用selenium在Firefox中的使用. 来源 少部分来源于书.python爬虫开发与项目实战 构造 本次使用简易的方案,模拟浏览器访问,然后输入字段,查找 ...

  9. python网络爬虫学习笔记(十一):Ajax数据爬取

    文章目录 1.基本介绍 2.基本原理 3.实战 有时候我们在用requests抓取页面的时候,得到的结果可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,但是使用requests得到 ...

  10. python爬虫爬取今日头条_Python爬虫实战入门五:获取JS动态内容—爬取今日头条...

    之前我们爬取的网页,多是HTML静态生成的内容,直接从HTML源码中就能找到看到的数据和内容,然而并不是所有的网页都是这样的. 有一些网站的内容由前端的JS动态生成,由于呈现在网页上的内容是由JS生成 ...

最新文章

  1. RHEL(RedHat Enterprise Linux)5/6 ISO镜像下载
  2. win8.1下jdk的安装和环境变量的配置 eclipse的安装和汉化
  3. 39道高级java面试题及答案(最新)
  4. linux 怎么添加path环境变量,Linux下怎么添加和查看PATH环境变量
  5. 这个可能打败Python的编程语言,正在征服科学界
  6. ASP.NET Web API中的返回值
  7. 数学建模 TOPSIS法
  8. unity3d与eclipse集成开发android应用
  9. php swf转image,gif转换swf|助你将gif图片转换成swf(flash)文件
  10. tf卡无法格式化怎么修复?解决方法分享
  11. Java类集框架——List接口
  12. homotopy-同伦_拔剑-浆糊的传说_新浪博客
  13. 禁用uwebiview 的反弹功能 bounces
  14. unitoy机器人怎么联网_乐乐智能机器人怎么联网?
  15. python代码画樱花-如何用Python画出一颗漂亮的樱花
  16. 91 q.v4p.co index.php,静觅丨崔庆才的个人站点
  17. QT实现文本编辑器(简易版)
  18. JS与DOM的兼容性
  19. BaziPickView 八字时间选择器、
  20. html+js 实现天气,JS实现天气预报查询

热门文章

  1. android开发 多语言和国际化
  2. 网线水晶头制作的线序
  3. LOJ6437 PKUSC2018 PKUSC
  4. Mac Excel 次坐标轴/双坐标轴/柱状图+折线图
  5. 网页加速优化简单总结
  6. 王者荣耀服务器不稳定总是跳频,vivo iQOO Pro 5G手机打玩王者荣耀网络不稳定出现断流...
  7. mysql跨库查询 效率_教你用一条SQL搞定跨数据库查询难题
  8. python 画图十大工具_python实现画图工具
  9. 23个可以免费学习编程的网站
  10. 【Python案例】用某度AI接口实现抠图并改图片底色