这是一篇介绍如何通过Python实现模拟登陆学校教务系统并爬取成绩相关信息(学期,课程名,总成绩,课程性质,学分)然后绘制成绩分布折线图最后导入MySQL数据库中的文章
为了利用充分利用selenium的功能和成功爬取数据,需要有前置的html、css、简单爬虫的相关知识

说明:我学校的成绩查询页面是通过加载js框架进而动态实时加载显示表格及数据的,如果仅仅是用一般的爬虫方法直接爬取页面信息,是不能成功的,因为那样是直接获取网页源码,其中并没有成绩数据。当然,采用某些爬虫方法肯定也能实现爬取js动态网页,但是我为了简单起见,直接用了selenium模拟登陆系统然后爬取信息。

一、导入主要模块

from bs4 import BeautifulSoup 
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
import matplotlib.pyplot as plt
import time
import pymysql

二、利用selenium模拟登陆教务系统

1.首先给出系统登陆页面url和成绩查询页面url(方便登陆成功后直接跳转,省去了鼠标点击相关链接的操作)

# 给出所需的url
url_login_page = ("你学校的教务系统登录页面url")
url_cjcx=("成绩查询页面url")

2.打开系统登录页面

# 启动Chorme驱动,开始模拟(不能用静默模式启动)
option = webdriver.ChromeOptions()
# 不加载图片,提高访问速度
option.add_argument('blink-settings=imagesEnabled=false')
driver = webdriver.Chrome(chrome_options=option)
driver.maximize_window()
print("正在访问......")
driver.get(url_login_page)

3.模拟输入账号密码并点击登陆按钮

这里需要你自己用F12去查看自己学校系统登陆页面的网页元素然后找到账号密码输入框、登录按钮的元素名称(这里我通过find_element_by_id找到了所需的输入框及按钮)

python编译成jar Python编译成绩登分册_mysql

# 自动输入账号密码
driver.find_element_by_id("username").send_keys("你的学号")
driver.find_element_by_id("password").send_keys("你的密码")

# 找到并点击登录按钮,实现登录
login_button = driver.find_element_by_id("login_submit")
actions = ActionChains(driver)
actions.key_down(Keys.CONTROL).click(login_button).key_up(Keys.CONTROL).perform()

三、爬取成绩信息

1.在新页面打开成绩查询页面

# 打开新的地址
driver.switch_to.window(driver.window_handles[-1])
driver.get(url_cjcx)

2.等待成绩查询页面加载完毕
我学校的查询页面与学校数据库对接较缓慢,所以我设置了10s等待时间,否则页面加载不出来会报错

# 等待页面加载完毕
time.sleep(10)

3.找到“每页显示50条数据”的按钮并点击

这里我想点击“每页显示50条数据”按钮是因为这样可以直接爬取所有数据而不需要点击“下一页”按钮。同样地,这里根据个人需要调整参数即可

python编译成jar Python编译成绩登分册_matplotlib_02

# 找到每页显示数目选择框并点击"50"
driver.find_element_by_class_name("bh-pull-right.jqx-widget.jqx-dropdownlist-state-normal.jqx-rc-all.jqx-fill-state-normal").click()
time.sleep(0.5)
driver.find_element_by_xpath("//span[text()='50']").click()

# 等待页面加载完毕
time.sleep(1)

4.爬取成绩查询页面的信息

这里采用的方法是先用driver.page_source+BeautifulSoup的方法获取当前页面的源码然后采用一般的爬虫方法获取相关信息

python编译成jar Python编译成绩登分册_python编译成jar_03

# 准备爬取成绩查询页面的信息
data = driver.page_source
soup = BeautifulSoup(data, 'lxml')
trs = soup.find_all("tr")
total_container = []
for tr in trs:
    row_container = []
    for span in tr:
        row_container.append(span.string)
    total_container.append(row_container)

# 初始化score subjects列表
score = []
subjects = []

# 输出最近两学期成绩数据
print("近两学期所有科目成绩如下:")
subject_num = int(len(total_container)/2)
for i in range(1,subject_num+1):
    print(total_container[i-1][1], total_container[i-1][2], total_container[i-1][6], total_container[i-1][9], total_container[i-1][11])
    subjects.append(total_container[i-1][2])
    score.append(total_container[i-1][6])
print("\n原始成绩:",score,"\n")

# 规范化成绩
for i in range(1,subject_num+1):
    if score[i-1] == '优秀' or score[i-1] =='621':
        score[i-1] = 95
    elif score[i-1] == '良好':
        score[i-1] = 85
    elif score[i-1] == '通过':
        score[i-1] = 75
    elif score[i-1] == None:
        score[i-1] = 98
    else:
        score[i-1] = int(score[i-1])

print("科目:",subjects,"\n")
print("规范化后的成绩:",score)

结果:

python编译成jar Python编译成绩登分册_爬虫_04

四、绘制成绩分布统计图

我们采用matplotlib.pyplot画图

# 绘图
print("\n正在绘制成绩分布折线图...")
x = range(subject_num)
# plt.xticks(x,subjects)  # 可以设置坐标字
plt.plot(x, score)
plt.xlabel("Subject(The xth)") #X轴标签
plt.ylabel("Score") #Y轴标签
plt.title('Score Distribution Chart')
plt.show()

结果:

python编译成jar Python编译成绩登分册_mysql_05

五、将数据导入MySQL

# 写入MySQL
print("\n正在连接MySQL服务\n...")
# 创建与测试数据库的连接
conn = pymysql.connect(host='localhost',user="root",password="你的密码",database="score_db")
# 输出创建的连接对象的信息
print("连接成功!\n连接对象的基本信息如下:")
print (conn)
print (type(conn))
cursor = conn.cursor()
print("开始向数据表插入爬取的内容...")
sql1 = ("INSERT INTO score_table_test(学期,课程名,总成绩,课程性质,学分) VALUES(%s,%s,%s,%s,%s)")
for i in range(1,subject_num+1):
    # param中是实际的表格数据
    param = (total_container[i-1][1], total_container[i-1][2], total_container[i-1][6], total_container[i-1][9], total_container[i-1][11])
    cursor.execute(sql1, param)
    conn.commit()
print("插入成功!")
# 清空表格内容
print("正在清空当前表格内容...")
sql2 = ("truncate table score_table_test")
cursor.execute(sql2)
conn.commit()
print("删除成功!")
# 关闭指针对象和连接对象
print("准备断开数据库连接....")
cursor.close()
conn.close()
print("已成功断开连接!")

结果:

python编译成jar Python编译成绩登分册_matplotlib_06

完整源码戳这里

欢迎小伙伴们fork or star其他项目哦~