强智系统爬虫分析
程序员文章站
2022-04-27 23:43:10
...
一、登录分析
我校使用的教务管理系统是叫做强智系统,有一天我就突发奇想想要搞一个爬虫去给他搞一搞。
1.刚开始我以为是非常简单的一个post请求就解决的事情,我就post了一个
data = {
username: 'xxxx',
password: 'xxxx',
RANDOMCODE: 'XXXX',
}
由于我还是太年轻,没有经历过反爬虫的毒打,果然返回了登陆失败。然后我就看了下网页源代码
咋回事?这玩意就提交了一个encoded和RANDOMCODE,竟然没有提交username和password。根据我多年的后端经验(假的,ε=ε=ε=┏(゜ロ゜;)┛)肯定这个encoded就是password和username进行加密编码后的产物。果然当我阅读他后面的一段js代码我发现了隐秘。
从中我们可以看到它通过一个叫encodeInp的函数进行加密(转码)然后把这两个通过%%%进行连接(好智障的一个设定)。然后我再一个叫做conwork.js的js文件中发现了这个函数。
找到这个文件就好解决了,我通过PyExecJs来调用这个js文件里面的函数。
登录代码如下
'''简单解析验证码'''
def parse_verity_code(session, img_url):
img_content = session.get(img_url)
img = Image.open(BytesIO(img_content.content))
img.save('a.png')
verify_image = Image.open('a.png')
code = pytesseract.image_to_string(verify_image)
time.sleep(2)
return code
'''
对账号密码进行编码
'''
def make_user_token(username, password):
with open('conwork.js') as f:
ctx = execjs.compile(f.read())
username_encode = ctx.call('encodeInp', username)
password_encode = ctx.call('encodeInp', password)
token = username_encode + '%%%' + password_encode
print(token)
return token
二、其他分析
其实在登录之后事情就变的简单多了,这管理系统没有那么多的反爬机制,所以你想干啥就能干啥。下面完整代码展示下,我这里隐去我们学校的网站
# encode: utf-8
import re
from io import BytesIO
import requests
from lxml import etree
from PIL import Image # 用于显示图片
import pymongo
import pytesseract
import time
import execjs
#
# MONGO_CLIENT = pymongo.MongoClient("mongodb://127.0.0.1:27017")
# mydb = MONGO_CLIENT['xxu_jwxt']
# mycol = mydb['score_list']
BASE_URL = "https://jwxt.xx大学.edu.cn"
SCORE_FOR_USER = []
USERNAME = '2017xxxxxx'
PASSWORD = 'xxxxxxxxxx'
def parse_verity_code(session, img_url):
img_content = session.get(img_url)
img = Image.open(BytesIO(img_content.content))
img.save('a.png')
verify_image = Image.open('a.png')
code = pytesseract.image_to_string(verify_image)
time.sleep(2)
return code
'''
对账号密码进行编码
'''
def make_user_token(username, password):
with open('conwork.js') as f:
ctx = execjs.compile(f.read())
username_encode = ctx.call('encodeInp', username)
password_encode = ctx.call('encodeInp', password)
token = username_encode + '%%%' + password_encode
print(token)
return token
'''
解析登录页面
'''
def parse_login(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
session = requests.session()
resp = session.get(url, headers=headers)
text = resp.text
html = etree.HTML(text)
img = html.xpath("//img/@src")[1]
img_url = BASE_URL + img
while True:
try:
code = parse_verity_code(session, img_url)
code = re.sub("[^\d\w]", '', code)
print("验证码:" + code)
login_url = BASE_URL + "/jsxsd/xk/LoginToXk"
print(login_url)
'''
用户名和密码会加密后以%%%连接
'''
encoded = make_user_token(USERNAME, PASSWORD)
data = {
'encoded': encoded,
'RANDOMCODE': code,
}
print(data)
rs = session.post(login_url, data) # 进行登录操作
# 成绩列表
score_page_url = 'https://jwxt.xxu.edu.cn/jsxsd/kscj/cjcx_list'
resp = session.get(score_page_url, headers=headers)
score_list = etree.HTML(resp.text)
data_list = score_list.xpath('//table[@id="dataList"]')[0]
scores = data_list.xpath(".//tr")[1:]
for score in scores:
tds = score.xpath(".//td")
goal_data = {
'id': tds[0].text,
'term': tds[1].text,
'cno': tds[2].text,
'cname': tds[3].text,
'score': tds[4].xpath('.//a/text()')[0],
'point': tds[5].text,
'total_point': tds[6].text,
'GPA': tds[7].text,
}
SCORE_FOR_USER.append(goal_data)
# mycol.save(goal_data) # 保存到mongo数据库中
print(goal_data)
if SCORE_FOR_USER: # 验证码正确 跳出循环结束程序
break
except:
print("验证码错误")
def main():
url = "https://jwxt.jsu.edu.cn/jsxsd/"
parse_login(url)
if __name__ == '__main__':
main()