其实之前有写过一篇帖子了

在之前使用教务系统的过程中,偶然一次发现登上教务系统后再退出来的后的登录网址竟然不需要验证码,想着之前有写过教务系统的爬虫模拟登录,没验证码的岂不是更好干(之前那次折腾了好久hhh,后面还是用selenium实现的成绩爬取,相比直接爬取,selenium的性能还是比不上毕竟selenium本来就是用来搞自动化的hhh),然后今天闲着就重写了相同的功能并实现了成绩的爬取。

简单写一下思路:百度直接搜索出来的教务系统网址是需要验证码的,登录上去之后,再退出来就得到不需要验证码的登录网址

c1179d7c65cde6c7c4e6d6d2905fa599.png点开我们可以发现是需要验证码的

e5b4ef5c84c795f2ed4db832907217e3.png

登录上去之后再退出,下图箭头所指:

dfc07ebfedf275a43a8bb611f6882ba0.png

退出之后,是不是神奇的发现验证码不见了(见下图)哈哈哈,这就是我们要的。

7fb26dcb407f81bba533eef6b33fd2ce.png正式开始我们的分析看了好一会儿后,发现自己根本看不懂,想着反正是调用的这个文件中的函数,那不如自己去改改代码调用encodeInp()函数,看能不能调用成功,输出跟调试工具中一样的encoded,如果是一样的我们目的就达到了,加密的过程就是在submitForm1()中调用encodeInp()函数,且跟cookie没关系,也就是说每个人的账号密码最后经过加密出来的字符串每次都是固定的。

77ee1543fe6e3ac6a57b674412f158ed.png

这里我就用了自己的账号密码,结果可以发现是一样的。

228e840d5c98c181cee6b25604b8c66f.png我们直接找到表单位置,可以注意到当点击登陆时会触发函数submitForm1() ==> 好嘞,这不好办吗?接下来就让我们来顺腾摸瓜

948ca5d6517767b4e658262f7ae48ea8.png

我们复制函数的名称,并直接ctrl+F查找到函数的位置

f46f4e904a2ed3709eb6e1a0df388ef3.png

仔细看看函数,不难发现函数取得到了表单中我们输入的账号密码后都调用了encodeInp()函数,然后组成了一个用变量encoded保存的字符串。

56da2f7271ad0c5d8e0bf20a4f5dd6e8.png

3.输入一个错误的账号密码,点击登录看看开发者调试工具里面network的情况

我们可以注意到红框中的那个post请求

6ece68bef9df1f0ecb944471a2f5581b.png

点开后,我们可以看到cookie,也不难发现encoded字样,于是我们可以猜测提交的表单中就只有这一个数据,且是登录验证的唯一一个数据(比之前那个贴简单太多了,自己流下了心酸的泪水)

1723a0650d511544c25f0060f81fcc72.png

接着分析,关掉浏览器,重新打开这个不要验证码的网址(重新获得服务端分配的一个cookie),输入跟刚刚错误的账号密码再看看那个encoded有没有变化,因为根据自己上次的经验encoded是根据每次分配的cookie不同而变化的.....然后我们发现是没有变化的!!!是没有变化的!!!是没有变化的!!!(重要的事情说三遍,这还不好办嘛???)

a44e26903deb18b31966352ad8b24b36.png上面说到点击网页上的登录按钮时会触发函数submitForm1(),然后在这个函数中又会调用对账号密码进行加工(其实是加密hhh)的encodeInp()函数,我们来找到encodeInp()函数的位置,相同的操作CTRL+F,结果发现函数不在这儿。

5260dc5f10afb0483ea81ada076c41a4.png

既然函数不在该页面的源代码中,肯定是引进来的js文件,我们在html的头部去找引入的文件,结果发现只引入了一个js文件,那么我们可以肯定encodeInp()函数就在该文件中了。

c99381cf8011dabbf0c073107bbd69b8.png

在点开的conwork.js文件中搜素encodeInp()函数,找到了!!!

b61930bd8163e8eb686d191b574d55c6.png

要分析,肯定是得要看网页源代码滴(鼠标右击查看网页源代码),当然还有F12提供的开发者调试工具

2b5a5f2d8089dc7371339037e060fdb7.png

85690f6d2602e62ca886ac4c52e02b10.png

2.让我们来看看网页源代码

继续顺腾摸瓜(战术性滑稽脸)

仔细看看conwork.js文件接下来我们就可以写python代码了我们先把conwork.js文件的代码和经过更改的且python的execjs库能调用的submitForm1()函数放在一个同一个js文件里面(这里我把函数名称换了一下,换成了encode)

be12a3c43be17a0f091146a40339d0c0.png

写代码的思路我就不说了,代码贴在下面了,不过这次我倒是惊奇的发现不加header都能直接登陆。import requests

import execjs

from bs4 import BeautifulSoup

class Login:

def __init__(self):

self.url = 'http://jiaowu2.hufe.edu.cn/jsxsd/'

header = {

"Content-Type": "text/html;charset=utf-8",

"Vary": "Accept-Encoding"

}

self.session = requests.session()

self.session.get(self.url,headers=header)

self.username = '****'#账号

self.password = '****'#密码

self.GetEncoded()

self.login()

def GetEncoded(self):#该函数获取加密后的字符串

with open(r'conwork.js', encoding='utf-8') as f:

js = execjs.compile(f.read())

self.encoded =  js.call('encode', self.username,self.password)

f.close()

return self.encoded

def login(self):

postData = {

'encoded': self.encoded.strip()  # 账号密码加密后的东西

}

return self.session.post('http://jiaowu2.hufe.edu.cn/jsxsd/xk/LoginToXk',data=postData)

def GetScore(self):#爬取全部课程成绩

response = self.session.get('http://jiaowu2.hufe.edu.cn/jsxsd/kscj/cjcx_list')

grade_html = response.text

soup = BeautifulSoup(grade_html, 'html.parser')

tr_lable = soup.find_all("tr")[1:]

all_rows = []  # 该列表存放每一个课程的详细信息。

all_rows.append([i.text for i in soup.find_all("th")])

for tr in tr_lable:

tds = tr.find_all('td')

row = []

for td in tds:

row.append(td.text)

all_rows.append(row)

return all_rows

test = Login()

test.login()

print(test.GetScore())#打印爬取的成绩

最后,代码肯定有很多写的不够好的地方,望大家多多包含。嘿嘿嘿~

Logo

惟楚有才,于斯为盛。欢迎来到长沙!!! 茶颜悦色、臭豆腐、CSDN和你一个都不能少~

更多推荐