Python 的概念
正式进入主题,每学期末都要抢课,学校的服务器还贼渣。
私信小编007即可自动获取大量Python视频教程以及各类PDF!
先说一个简单的的方法,抓包,不断地发起选课请求,但有一个明显的缺点,那就是cookies容易过期。
还得重新登陆替换cookies。于是,就有了今天要分享的内容。
其大概分为两个部分:1.自动登录教务处;
2.查看成绩、抢课.
考虑到有些童鞋没有图像处理的经验,我会把训练好的结果直接给大家。今天先写第一个自动登录。
自动登录教务处
自动登陆教务处时,解决两个主要问题:** 1.验证码的识别;2.cookies的获取**
验证码识别
<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">1. 想要识别验证码,最起码知道验证码的url才能下载下来。其url地址:http://{}/CheckCode.aspx {}
</pre>
代表着相应的域名或ip地址。
2. 将验证码下载下来,其代码十分简单,后面会给放上代码的。得到验证码。如下图
学生利用python破解验证码,模拟登录教务处查看成绩、抢课!3.接下来的过程很重要,对验证码进行数字图像处理,把图片里的字母一个个的分割出来。怎么做呢?
3.1先观察图像中的字符都蓝色的,可以提取RGB三色通道中的B通道。得到图像
学生利用python破解验证码,模拟登录教务处查看成绩、抢课!3.2注意到图片中的小点点了没有,在数字图像中,这种情况称之为椒盐噪声,对这种噪声的处理呢,一般用的方法是中值滤波,当然,也可 以根据B通道图像的特点,自己写一个更合适的算法。这里时间比较紧,就直接采用中值滤波,并图像增强,得到图像
学生利用python破解验证码,模拟登录教务处查看成绩、抢课!3.3 嗯,在这里补充一点,我觉得自己写的算法应该比这种普遍的处理方法要好的多,强烈建议有能力的童鞋自己写一写,估计github、博客上已经有相关代码了。得到上图像,将图像进行二值化,先观察期灰度分布直方图,确定阈值为160(当然阈值可以适当的调整),最后,进行二值化。
学生利用python破解验证码,模拟登录教务处查看成绩、抢课!灰度直方图
学生利用python破解验证码,模拟登录教务处查看成绩、抢课!二值化之后的图像
3.4 将图片分割成单个的字符,采用的分割距离为[5,16,29,38,53]
学生利用python破解验证码,模拟登录教务处查看成绩、抢课!效果图
学生利用python破解验证码,模拟登录教务处查看成绩、抢课!全部分割完成
3.5 将得到的字符串与正确的验证码用机器学习中的KNN算法进行训练,当然也可以用RNN等算法,它的精确度什么的统统没计算,感觉准确度在80%左右。我的小破笔记本跑不了很多数据,见谅呀!
当然,你也可以采用不同的算法进行训练,其性能什么的可以做一下比对。得到结果集,保存出来,为下一次预测准备。放心吧,得到的结果以附件的形式发出来的。直接拿来用就好了。
以上内容呢,虽然没有代码,但是思路已经写得很清楚了,我写的代码有点乱,有点不好意思发出来。想要的话可以在帖子下面留言,如果想看的人多的话,我会整理整理发出来的。哦,差点忘了,所用的库有 numpy、PIL(2.7.x,三对应版本应该是pillow-pil记不太清了)、sklearn matplotlib
自动登录
在写以前呢,先大体看一下它的结构
学生利用python破解验证码,模拟登录教务处查看成绩、抢课!解释一下,cache下面存放的是验证码,ImageIdentification下面的图像处理+识别的相关函数 model下存放的是训练好的结果,network下是关于网络请求的一些类。在写的过程中用了一点点面向对象的思想所以,抽象出一个config类,通过方正系统的一个分析,他在页面里隐藏着很重要的一个数据叫做__VIEWSTATE,在每次请求中都要用到,所以config的代码如下:
<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># encoding=utf-8[/align]import requests
from bs4 import BeautifulSoup
import urllib
class config(object):
'''
抽象出的父类
'''
def init(self,url):
self.ip="xxx.xxx.xxx.xxx"
self.url=url.format(self.ip)
self.headers = {
'Accept': 'text/html,application/xhtml+xm…plication/xml;q=0.9,/;q=0.8',
'Accept-Encoding': 'gzip, deflate',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Content-Type': 'application/x-www-form-urlencoded',
'Host': self.ip,
'Pragma': 'no-cache',
'Referer': self.url,
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0'
}
def getVaules(self,cookies=''):
html = requests.get(self.url,headers=self.headers,cookies=cookies)
soup = BeautifulSoup(html.content, 'html.parser', from_encoding='gbk')
__Value = soup.find('input', {'type': 'hidden', 'name': '__VIEWSTATE'})
return urllib.quote_plus(__Value.get('value'))
</pre>
在登录的过程中肯定需要cookies,那么cookies怎么获取,才能使验证码不报错呢?这个也很简单,在获取验证码时,同时获取到验证码的cookies,在登录时填入验证码的cookies就可以实现。代码如下
<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># encoding=utf-8
from BaseClass import config
import requests
class cookie(config):
def getcookies(self):
content=requests.get(self.url,headers=self.headers)
with open('./cache/yzm.png', 'wb') as f:
f.write(content.content)
return content.cookies
</pre>
前面铺垫了那么多,终于要写登录了,登录是不是要先抓包!抓到请求参数:__VIEWSTATE={}&txtUserName={}&Textbox1=&TextBox2={}&txtSecretCode={}&RadioButtonList1=%D1%A7%C9%FA&Button1=&lbLanguage=&hidPdrs=&hidsc=
__VIEWSTATE:这个参数在网页中已经有了,只需要解析出来,就行了。
txtUserName:这个参数代表 学号
TextBox2:表示密码
txtSecretCode:表示验证码
RadioButtonList1:这个后面解码出来,代表着学生(gbk编码),
代码如下
<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># encoding=utf-8
import requests
from BaseClass import config
from bs4 import BeautifulSoup
import urllib
class login(config):
def init(self,url):
self.data = '''__VIEWSTATE={}&txtUserName={}&Textbox1=&TextBox2={}&txtSecretCode={}&RadioButtonList1=%D1%A7%C9%FA&Button1=&lbLanguage=&hidPdrs=&hidsc='''
super(login,self).init(url)
def login(self,xh,pwd,yzm,cookies):
try:
data=self.data.format(self.getVaules(cookies=cookies),xh, pwd, yzm)
s=requests.session()
s.cookies=cookies
con = s.post(self.url, headers=self.headers, data=data)
if con.url==self.url:
print("验证码可能出现错误!请重新登陆")
print(con.content.decode('gbk'))
return False,None,None,None,
else:
data=con.content
soup=BeautifulSoup(data,'html.parser',from_encoding='gbk')
xm=soup.find('span',attrs={'id':'xhxm'}).text[0:len(soup.find('span',attrs={'id':'xhxm'}))-3]
print(xm)
return True,cookies,xh,xm
except Exception, e:
print(e.args)
print(e.message)
print e.doc
print(u"出现错误!请重新登陆")
return False,None,None,None,
</pre>
图像处理代码
<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># encoding=utf-8
from PIL import Image,ImageFilter
def process():
file_path='./cache/yzm.png'
split_lines = [5,17,29,41,53]
img=Image.open(file_path)
img = img.convert('RGB')
r, g, b = img.split()
image_b_median = b.filter(ImageFilter.MedianFilter())
image_b_median_binary = image_b_median.point(lambda i: i > 160, mode='1')
c = 1
for x_min, x_max in zip(split_lines[:-1], split_lines[1:]):
image_b_median_binary.crop([x_min, 0, x_max, 22]).save('./cache/yzm-{}.png'.format(c))
c = c + 1
print(u"图片处理完成")
</pre>
预测代码
<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># encoding=utf-8
from sklearn.externals import joblib
from PIL import Image
import numpy as np
def predict():
photo_path='./cache/yzm-{}.png'
X = []
for i in range(1,5):
img = Image.open(photo_path.format(i))
ls = np.array(img).tostring()
ls=np.fromstring(ls,dtype=bool)
X.append(ls)
file_path = './model/knn.pkl'
knn=joblib.load(file_path)
ls=knn.predict(X)
return "".join(ls)</pre>
网友评论