python 绕过国科大教务系统获取所有学生成绩

Posted 陆嵩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 绕过国科大教务系统获取所有学生成绩相关的知识,希望对你有一定的参考价值。

python 绕过国科大教务系统爬取十万学生成绩

我发现国科大的教务系统有 bug,今天早上我绕到后台,用 python 爬取了国科大在读和已毕业所有人的成绩,包括本科生和研究生。因为涉及隐私,我也就自己看看,不会跟别人说。只不过系统的这个漏洞,还是希望技术人员能够快点修复吧。

get 和 post 的基本用法

urllib 和 requests 都可以做 get 和 post 请求,我理解的 requests 是封装了 urllib 的更上层的一个东西。所以,没有什么特别要求,简单方便地,我们用 requests 就行了。他们的一个基本模板如下。
get 方式请求:

import requests
stuID = "xxxxxxxxxxxxxxx"
url = "xxx"+stuID
r = requests.get(url)

# requests提供了 params 关键字参数来传递参数
parameter = {
            "key1":"value1",
            "key2":"value2"
            }
response = requests.get("http://httpbin.org/get",params = parameter)
print(response1.url)
# 输出 http://httpbin.org/get?key1=value1&key2=value2

post 方式请求:

import requests
payload = {
    "key1":"value1",
    "key2":"value2"
}
response = requests.post("http://httpbin.org/post",data = payload)
print(response.text)

import requests
postdata = { 'name':'aaa' }
r = requests.post("http://xxxxx",data=postdata)
print(r.text)

#如果要爬虫用的话 一般建议带上session会话和headers表头信息,session会话可以自动记录cookie
s = requests.Session()
headers = { 'Host':'www.xxx.com'}
postdata = { 'name':'aaa' }
url = "http://xxxxx"
s.headers.update(headers)
r = s.post(url,data=postdata)
print(r.text)

#可以直接带上 header
import requests
import json
 
data = {'some': 'data'}
headers = {'content-type': 'application/json',
           'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}
 
r = requests.post('https://api.github.com/some/endpoint', data=data, headers=headers)
print(r.text)

简单地来说就是,r = requests.get(url)r = requests.post(url),然后有一些多余的参数可选。这是基本的已给 get 和 post 框架,其它的,根据后续需求查查百度修修补补即可。

做一个简单的 GUI 界面

除了批量爬取,我们也可以获取单个学生的成绩。比如说,某个时刻你对某个学霸同学的成绩很感兴趣,查!!!
做了一个简单的 GUI 界面。泄露传播别人的隐私是违法行为,代码和工具我就不公开了。
我装的是 anaconda,我不知道它把 pyqt5 放哪了。打开 Everthing 搜一下,喏,绿色的那个就是。

然后就是:

  • 新建对话框,带确定按钮那种。
  • 拖一个 Line Edit 用来输入学号,拖一个 Label 用来写"学号"两个字。摆好位置,添一添布局。保存 ui 文件。
  • 用 pyuic5 把 ui 文件转成 py 文件,pyuic5 用法类似于一般的格式转化工具。打开终端,执行 pyuic5 .\\untitled.ui -o dlg.py
  • 然后把生成出来的界面文件,import 进去用就行了。一个基本用它的框架模板是:
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    from PyQt5.QtWidgets import QInputDialog, QLineEdit, QDialog
    from PyQt5.QtWidgets import QApplication
    import sys
    #import dlg //不要这样写,应该写下面一个
    from dlg import *
    class TestDialog(QDialog,Ui_Dialog):  
        def __init__(self,parent=None):  
            super(TestDialog,self).__init__(parent)  
            self.setupUi(self)
    
    app=QApplication(sys.argv)  
    dialog=TestDialog()  
    dialog.show()  
    app.exec_()
    
    #下面这部分是主程序,需要简单改改
    import requests
    #stuID = "xxxxxxxxxxxxxxx"
    stuID = dialog.lineEdit.text() 
    #尊重隐私,后文省略
    

注意两点:1、命名 ui 文件生成的 py 文件时,可以自己命名,但是不能和 python 搜索路径下的文件重名,为了防止这一点,最后有一个特别的名字。2、导入自己的模块,写 from dlg import * 而不写 import dlg 否则可能会出现找不到。

运行出对话框,如下:

解析方法的选择

网页的解析方法,我们可以选择 BeautifulSoup、lxml(XPath ) 和正则表达式。这些我都用过,推荐 lxml,因为浏览器可以直接 Copy 你选中部分的 Xpath 表达。XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。

基本介绍:

/ 从根节点选取
// 从所有匹配的节点选取
. 当前节点
.. 当前的父节点
nodename 选取节点
@ 选取节点的属性
* 通赔符 
| 选取若干路径用分割
text() 选取该节点的文本内容

例子:
//img/@src 选取所有img 节点的src属性
//img/../text 选取img节点的父节点下的text节点
//*/@src 选取任何节点的 src 属性
result = html.xpath('//a/@href')
print(result)


result = html.xpath('//div/text()')
print(result)
result = html.xpath('//div//text()')

# string 也是一种函数方法,可以提取子标签的文本
content = code.xpath('//div[@class="p_content  "]/cc/div')
for i in content:
	print(i.xpath('string(.)'))

一个基本的写法框架模板是:

import requests
from lxml import etree
from chardet import detect
url = "xxxxx"
r = requests.get(url)
# html=r.content
# cder=detect(html)
# html=html.decode(cder.get('encoding'))
html=r.text

tree=etree.HTML(html)
# tmp = etree.tostring(tree)
# print(tmp)
name = tree.xpath('/html/body/div/table[3]/tr[1]/td[2]/font')
print('result is: '+name[0].text)

代码结构

部分代码展示如下:

dlg.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file '.\\test.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(400, 300)
        self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
        self.buttonBox.setGeometry(QtCore.QRect(30, 240, 341, 32))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.label = QtWidgets.QLabel(Dialog)
        self.label.setGeometry(QtCore.QRect(50, 120, 312, 31))
        self.label.setObjectName("label")
        self.lineEdit = QtWidgets.QLineEdit(Dialog)
        self.lineEdit.setGeometry(QtCore.QRect(140, 120, 252, 31))
        self.lineEdit.setObjectName("lineEdit")

        self.retranslateUi(Dialog)
        self.buttonBox.accepted.connect(Dialog.accept)
        self.buttonBox.rejected.connect(Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.label.setText(_translate("Dialog", "学号"))
        self.lineEdit.setText(_translate("Dialog", "201900000000000"))


main.py

from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QInputDialog, QLineEdit, QDialog
from PyQt5.QtWidgets import QApplication
from lxml import etree
from chardet import detect
import sys
#import dlg //不要这样写,应该写下面一个
from dlg import *
class TestDialog(QDialog,Ui_Dialog):  
    def __init__(self,parent=None):  
        super(TestDialog,self).__init__(parent)  
        self.setupUi(self)

app=QApplication(sys.argv)  
dialog=TestDialog()  
dialog.show()  
app.exec_()

#下面这部分是主程序,需要简单改改
import requests
#stuID = "xxxxxxxxxxxxxxx"
stuID = dialog.lineEdit.text() 
url = "xxxxx"
r = requests.get(url)

html=r.text
tree=etree.HTML(html)
tmp = etree.tostring(tree)
print(tmp)
name = tree.xpath('/html/body/div/table[3]/tr[1]/td[2]/font')
print('result is: '+name[0].text)
f = open(name[0].text+stuID+".html",'w+',encoding='utf-8')
#print(r.text)
f.write(html)

HTML 和 javascript

为了使用更方便的快捷,除了桌面程序,我还写了一个 H5 的小脚本,效果如下。


部分前端代码如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>
			国科大成绩查询
		</title>
		<link href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css"
		rel="stylesheet">
		<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.js">
		</script>
		<style type="text/css">
			html,body{width:100%;height:100%;margin:0;font:14px "Microsoft Yahei","微软雅黑",Tahoma,Arial,Helvetica,STHeiti;color:#ccc;background-color:#27ae60;}.logo{width:150px;height:64px;background:url(./images/spite_index)
			-29px -432px no-repeat;margin:80px auto 20px;}.header{color:#f4f4f4;margin-bottom:15px;font-size:21px;font-weight:200;text-align:center;}.header
			span{font-size:14px;}.form-group{margin-top:40px;margin-bottom:15px;}.form-group
			.text{width:450px;border:2px solid #27ae60;-webkit-box-shadow:none;box-shadow:none;font-size:16px;padding:13px
			30px;border-radius:0;height:auto;text-align:center;margin:10px auto;}.form-group
			.text:focus{border-color:#208d4e;}a.submit{width:446px;background:#239650;border:1px
			solid #239650;-webkit-box-shadow:none;box-shadow:none;font-size:18px;color:#fff;padding:10px
			30px;border-radius:0;height:auto;text-align:center;margin:0 auto;}a:hover{cursor:pointer;text-decoration:none;background:#208d4e;border-color:#208d4e;}.tip{width:375px;height:87px;background:url(./images/spite_index)-21px
			-513px;margin:80px auto 0;}
		</style>
		<script type="text/javascript">
			$(function() {
				$('#submit').on('click',
				function() {
					var input = $('input[name=input]').val().replace(/(^\\s*)|(\\s*$)/g, "");
					window.open('xxx' + input + '?xxx');
				})
			});
		</script>
	</head>
	<body>
		<div class="container">
			<div class="logo">
			</div>
			<p class="header">
				陆嵩小主,请输入您要查询的学号
				<br/>
				<div class="form-group">
					<input type="text" class="form-control text" name="input" value="" placeholder="输入学号"
					/>
					<a id="submit" class="form-control submit">
						获取成绩
					</a>
				</div>
			</p>
			<div class="tip">
			</div>
		</div>
	</body>

</html>

以上是关于python 绕过国科大教务系统获取所有学生成绩的主要内容,如果未能解决你的问题,请参考以下文章

python爬虫获取强智科技教务系统学科成绩(模拟登录+成绩获取)

C#课程设计之学生教务管理系统

【教务管理篇】多维度学生成绩分析,全方位把控教学质量

网络爬虫入门——案例二:爬取教务系统中的学生成绩

基于php006教务选课学生选课成绩管理系统

Java实验报告——教务系统(继承)