目录

破解之江汇验证码实现自动赚分

之江汇的验证码是很简单的2位数加法。一开始用的是猜答案的办法登录,就是把可能的答案做成一个列表。然后循环登录。直到登录成功。这个效率很低。后来发现它的子网站可以不用验证码登录在用。登录子网站再用token同步登录主网站这个方法用了很长的时间。现在也不能用了。最后是用百度的ocr库AIP很好用。但是现在要收费了。然后就在网上找各种ocr方法。像easyocr和Google的Tesseract-OCR好像都要安装底层软件。好像很麻烦。而且大炮打蚊子。浪费资源,只是0-9的验证码识别。没那个必要了。于是就有了这个用Pil图片处理库直接破解验证码的代码。

1. 获取验证图片

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def get_code():
    url = "http://yun.zjer.cn/index.php?r=portal/Vcode/GetNewCode"
    headers = {'Accept': 'application/json, text/javascript, */*; q=0.01',
                'Host': 'yun.zjer.cn',
                'Origin': 'http://yun.zjer.cn',
                'Referer': 'http://yun.zjer.cn/space/index.php?r=portal/user/login',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36',
                'X-Requested-With': 'XMLHttpRequest'} 
    r = req.get (url,headers=headers).json()
    t = r['imageinfo']
    v = r['passCode']
    return t,v

这个函数获取验证码的图片内容和登录时要用的一个验证字符段。

2. 解码图片内容

1
2
3
4
5
6
7
8
9
def decode_image(src):
    result = re.search("data:image/(?P<ext>.*?);base64,(?P<data>.*)", src, re.DOTALL)
    if result:
        ext = result.groupdict().get("ext")
        data = result.groupdict().get("data")
    else:
        raise Exception("Do not parse!")
    img = base64.urlsafe_b64decode(data)
    return img

这个验证码图片是用base64封装的图片,用base64解码一下就好了

3. 处理图片并切割

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def shibie(src):
    img_data = decode_image(src)
    img = Image.open(BytesIO(img_data))
    w,h=img.size
    img=img.convert('RGB')
    r1,g1,b1 = img.getpixel((0,0))

    for i in range(w):
        for j in range(h):
            pix2 = img.getpixel((i,j))
            if sum(pix2) < 750 :
                img.putpixel((i,j),(0,0,0))
    img1 = img.crop((4,6,14,18))
    img2 = img.crop((13,6,23,18))
    img3 = img.crop((44,6,54,18))
    img4 = img.crop((53,6,63,18))
    a = getnum(get_point(img1))
    b = getnum(get_point(img2))
    c = getnum(get_point(img3))
    d = getnum(get_point(img4))
    if b == None : 
        num1 = a 
    else :
        num1 = a*10+b   
    
    if d == None :
        num2 = c 
    else :
        num2 = c*10+d
    draw_num(img)
    result = int(num1)+int(num2)
    return result

3.1 处理图片转成rgb格式。

1
img=img.convert('RGB')

3.2 遍历图片将不需要的杂点和和背景色全部改成黑色

1
2
3
4
5
    for i in range(w):
        for j in range(h):
            pix2 = img.getpixel((i,j))
            if sum(pix2) < 750 :
                img.putpixel((i,j),(0,0,0)) 

3.3 切割图片

1
2
3
4
    img1 = img.crop((4,6,14,18))
    img2 = img.crop((13,6,23,18))
    img3 = img.crop((44,6,54,18))
    img4 = img.crop((53,6,63,18))

4. 遍历图片找出特征点

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def get_point(img):
    point = ""
    w,h=img.size
    for i in range(h):
        p1 = 0
        for j in range(w):
            if img.getpixel((j,i)) == (255,255,255) :
                p1 += 1
        point += str(p1)
    return point

从上往下遍历图片找出白色像素点形成特征码。因为字形不一样。特征码肯定是唯一的。

5. 根据特征码找出数字

1
2
3
4
5
6
def getnum(p):
    num_list = ["024444444420","023422222260","044422222280","054223222450","023444482220","072255224440","044325544440","082222222220","044444444440","044445523440",]
    for num,i in enumerate(num_list):
        if p == i :
            return num 
    return None

6. 在终端画出字符画验证识别准备率

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def draw_num (img):
    w,h=img.size
    for i in range(h):
        p1 = ""
        for j in range(w):
            if img.getpixel((j,i)) == (255,255,255) :
                p1 += " "
            else :
                p1 += "1"
        print (p1)

准确率还是很高的。基本接近百分之百。 验证码识别成功后一个post就很简单的可以实现自动登录,登录后就可以模仿电脑端操作刷分了。

完整代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2021-12-02 22:43:55
# @Author  : xzap (xzap@163.com)
# @Version : 1.1

import retry
import time
import os
import sys
import re
import requests
from PIL import Image
import base64
from io import StringIO,BytesIO
from retry import retry
import time
import pickle

def get_time():
     return int(time.time()*1000)

def decodeS(string):
    string = string.encode()
    result = base64.b64encode(string).decode()
    key = "tPhCyUsKpXlHsEgSyHoEkLdQpLkOsLcYhErFkWxJsFeVhLiQrHqFbYbNyEvClEwUfQmEgUnEfJiHfPtLuEdDbIiIqUqLoTzOmYqA"
    key_login = '95a1446a7120e4af5c0c8878abb7e6d2'
    keyLen =  len(key)
    code = ''
    for i in range(len(result)):
        k = i % keyLen
        n = ord(result[i]) ^ ord(key[k])
        code += chr(n)

    code = base64.b64encode(code.encode()).decode()
    newcode = ""
    for i in range(len(code)):
        t1 = code[i]
        t2 = ""
        if key[i]:
            t2 = key[i]
        newcode += t1 + t2
    newcode = newcode.replace("/","6666cd76f96956469e7be39d750cc7d9")
    newcode = newcode.replace("=", "43ec3e5dee6e706af7766fffea512721");
    newcode = newcode.replace("+", "26b17225b626fb9238849fd60eabdf60"); 
    newcode = key_login + newcode 
    return newcode

def decode_image(src):
    result = re.search("data:image/(?P<ext>.*?);base64,(?P<data>.*)", src, re.DOTALL)
    if result:
        ext = result.groupdict().get("ext")
        data = result.groupdict().get("data")
    else:
        raise Exception("Do not parse!")
    img = base64.urlsafe_b64decode(data)
    return img

def get_point(img):
    point = ""
    w,h=img.size
    for i in range(h):
        p1 = 0
        for j in range(w):
            if img.getpixel((j,i)) == (255,255,255) :
                p1 += 1
        point += str(p1)
    return point

def draw_num (img):
    w,h=img.size
    for i in range(h):
        p1 = ""
        for j in range(w):
            if img.getpixel((j,i)) == (255,255,255) :
                p1 += " "
            else :
                p1 += "1"
        print (p1)

def getnum(p):
    num_list = ["024444444420","023422222260","044422222280","054223222450","023444482220","072255224440","044325544440","082222222220","044444444440","044445523440",]
    for num,i in enumerate(num_list):
        if p == i :
            return num 
    return None

def shibie(src):
    img_data = decode_image(src)
    img = Image.open(BytesIO(img_data))
    w,h=img.size
    img=img.convert('RGB')
    r1,g1,b1 = img.getpixel((0,0))

    for i in range(w):
        for j in range(h):
            pix2 = img.getpixel((i,j))
            if sum(pix2) < 750 :
                img.putpixel((i,j),(0,0,0))
    img1 = img.crop((4,6,14,18))
    img2 = img.crop((13,6,23,18))
    img3 = img.crop((44,6,54,18))
    img4 = img.crop((53,6,63,18))
    a = getnum(get_point(img1))
    b = getnum(get_point(img2))
    c = getnum(get_point(img3))
    d = getnum(get_point(img4))
    if b == None : 
        num1 = a 
    else :
        num1 = a*10+b   

    if d == None :
        num2 = c 
    else :
        num2 = c*10+d
    # draw_num(img)
    result = int(num1)+int(num2)
    return result


def get_code(req):
    url = "http://yun.zjer.cn/index.php?r=portal/Vcode/GetNewCode"
    headers = {'Accept': 'application/json, text/javascript, */*; q=0.01',
                'Host': 'yun.zjer.cn',
                'Origin': 'http://yun.zjer.cn',
                'Referer': 'http://yun.zjer.cn/space/index.php?r=portal/user/login',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36',
                'X-Requested-With': 'XMLHttpRequest'} 
    r = req.get (url,headers=headers).json()
    t = r['imageinfo']
    v = r['passCode']
    return t,v

# @retry(tries=3, delay=5)
def do_login (user,passwd,req,session):
    user = decodeS(user)
    passwd = decodeS(passwd)
    img, vaildata = get_code(req)
    valcode = shibie(img)
    url = "http://yun.zjer.cn/index.php?r=portal/user/loginNew"
    data = {"userId": user,
        "userPsw": passwd,
        "remember":"1", 
        "vaildata": vaildata,
        "valCode": valcode,
        "service" : ""
        }
    j = req.post(url,data=data)
    # print (j.json())
    token = j.json()["token"]
    url = "http://yun.zjer.cn/space/index.php?r=uc/site&callback=jQuery015164962438537555_%s&platformCode=%s&school=0&_=%s" % (get_time(),j.json()["platformCode"],get_time())
    c = req.get(url)
    url_list = [
    "http://space.zjjxedu.gov.cn:10000/index.php",
    "http://yun.zjjxedu.gov.cn/index.php",
    "http://jsjy.space.zjjxedu.gov.cn:10000/index.php",
    "http://jsjy.zjjxedu.gov.cn/index.php",
    "http://yun.zjer.cn/index.php",
    "http://yun.zjer.cn/space/index.php", # 只有这个也能查分 
    "http://sns.zjer.cn/index.php",
    ]
    for url in url_list:
        params = {
        "r": "uc/loginToken",
        "callback": "jQuery015164962438537555_%s" % get_time(),
        "token": token,
        "_": get_time()
        }
        req.get(url,params=params)
    url = j.json()["url"]
    req.get(url)
    with open(session,"wb") as f :
        pickle.dump(req.cookies, f)

def shuafen(req):
    url = "http://yun.zjer.cn/space/index.php?r=center/person/index"
    c = req.get(url).text
    kid = re.search('"widgets.mm_center_person.40.index.userinfo.UserInfoWidget" data-kid="([^"]*)"', c).group(1)
    kid_url = "http://yun.zjer.cn/space/index.php?r=widget&classname=widgets.mm_center_person.40.index.userinfo.UserInfoWidget&kid=%s&_=%s" % (kid,get_time())
    c = req.get(kid_url).text
    jifen = re.search('<em class="mgr5 f12">(.*)</em>', c).group(1)
    name = re.search('onclick="return false;" class="c555" title="(.*)">(.*)</a>', c).group(1)
    print ("%s 登录成功,现有积分 %s 分!" % (name,jifen))
    shuafen = [
    "http://yun.zjer.cn/space/index.php?r=space/person/visitor/index&sid=90231",
    "http://yun.zjer.cn/space/index.php?r=space/person/visitor/index&sid=254633",
    "http://ke.zjer.cn/index.php?r=curricula/syncourse/play&kcid=308270&ksid=1557196148",
    "http://jdx.zjer.cn/index.php?r=studio/courselive/Livelist&sid=600061&tid=9525&aid=4043&xs_id=1&on_sale=1",
    "http://ms.zjer.cn/index.php?r=studio/live/livebackdetail&sid=824&id=3159&live_type=1",
    "http://ms.zjer.cn/index.php?r=studio/live/livebackdetail&sid=603&id=2617&live_type=3",
    "http://ms.zjer.cn/index.php?r=studio/live/livebackdetail&sid=551&id=97&live_type=1"
    ]
    for url in shuafen :
        c = req.get(url)
    sh = "http://yun.zjer.cn/space/index.php?r=widgets/mm_center_person/index/res_examine/resExamine/reslist&key=1"
    c = req.get(sh).text
    if "去审核" in c :
        r = re.search('href="([^"]*)">去审核</a>',c).group(1)
        c2 = req.get(r).text
        r2 = re.search('resId=(.*)',r).group(1)
        data = {"resId": r2,
            "status": 1}
        req.post("https://yun.zjer.cn/res/recommendEssence.do",data=data)
        print ("审核成功")
    else :
        print ("无审核")
    url = "http://yun.zjer.cn/index.php?r=widgets/mm_center_person/35/ucenter/integral/Integral/Integral"
    c = req.get(url).text
    jifen2 = re.search('<p class="f16 blue mgt10"><strong class="f30">(.*)</strong>分', c).group(1)
    print ("现有积分 %s 分,增加了 %s 分。" % (jifen2,int(jifen2)-int(jifen)) )
    print ("_"*40)
    logout = "http://yun.zjer.cn/index.php?r=uc/logout"
    req.get(logout)



user_list = [
    ("用户名1","密码1"),
    ("用户名2","密码2"),
]

for i in user_list:
    flag = False
    fdir = os.path.join(os.path.abspath(os.path.dirname(__file__)),"sessions")
    if not os.path.exists(fdir):os.mkdir(fdir)
    session = os.path.join(fdir,"session-%s" % i[0])
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36',} 
    req = requests.session()
    req.headers.update(headers)
    if not os.path.exists(session):
        flag = True
    else:
        with open(session, 'rb') as f:
            req.cookies.update(pickle.load(f))
    test_url = "http://yun.zjer.cn/index.php?r=center/person/index"
    c = req.get(url=test_url,timeout=5)
    if "登录" in c.text:
        flag = True
    if flag :
        print ("本地Session无效,开始重新登录……")
        do_login(i[0], i[1], req, session)
    shuafen(req)