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 绕过国科大教务系统获取所有学生成绩的主要内容,如果未能解决你的问题,请参考以下文章