【腾讯云 Cloud Studio 实战训练营】使用Cloud Studio制作蛋仔派对兑换码工具

在这里插入图片描述

目录

  • 🍳前言
  • 🍳实验介绍
  • 🍳产品介绍
  • 🍳抓包分析
    • 😃登录分析
      • 😃😃第一步,获取验证码
      • 😃😃第二步,保存验证码
      • 😃😃第三步,识别验证码
      • 😃😃第四步,实现登录
    • 😃兑换操作分析
  • 🍳实际操作
    • ⭐注册Cloud Studio
    • ⭐新建python项目(不选用模板)
      • ⭐⭐创建项目
      • ⭐⭐填写模板信息
      • ⭐⭐选择环境镜像
    • ⭐代码操作
      • ⭐⭐获取验证码
      • ⭐⭐保存验证码
      • ⭐⭐识别验证码
        • ⭐⭐⭐ddddocr修复bug
      • ⭐⭐接口鉴权
      • ⭐⭐福利码兑换
    • ⭐构建GUI视图
      • ⭐⭐绘制可视化界面
      • ⭐⭐获得视图层代码
      • ⭐⭐代码事件封装
      • ⭐⭐软件打包
  • ⭐总结

🍳前言

Cloud Studio 是基于浏览器的集成式开发环境(IDE),为开发者提供了一个永不间断的云端工作站。用户在使用 Cloud Studio 时无需安装,随时随地打开浏览器就能在线编程。 Cloud Studio 作为在线 IDE,包含代码高亮、自动补全、Git 集成、终端等 IDE 的基础功能,同时支持实时调试、插件扩展等,可以帮助开发者快速完成各种应用的开发、编译与部署工作。 所以,本次开发蛋仔派对兑换码工具优先采用在线IDE-Cloud Studio,让我们随着本项目对Cloud Studio进行探索吧~

案例环境:

  • python

模块:

  • datetime
  • json
  • re
  • tkinter

🍳实验介绍

通过本次项目实战,实现一个可视化的小工具,可批量操作兑换码
在这里插入图片描述


🍳产品介绍

Cloud Studio 是基于浏览器的集成式开发环境(IDE),为开发者提供了一个永不间断的云端工作站。用户在使用 Cloud Studio 时无需安装,随时随地打开浏览器就能在线编程。 Cloud Studio 作为在线 IDE,包含代码高亮、自动补全、Git 集成、终端等 IDE 的基础功能,同时支持实时调试、插件扩展等,可以帮助开发者快速完成各种应用的开发、编译与部署工作。


🍳抓包分析

在进行写代码前,我们进行流程分析,否则无从下手,这是蛋仔派对的兑换人口
在这里插入图片描述

😃登录分析

暂且就叫登录吧,因为它的第一步是输入游戏ID进行查询,才有后面的兑换操作

😃😃第一步,获取验证码

登录需要验证码,通过Stream,我们进行正常的兑换测试【图1-1】,发现在首页打开时会触发获取验证码的接口【图1-2】,这是抓包响应结构:

{"status": true, "base64": "/9j*****Q==", "ctoken_id": "e8814dbbec8348ea8b0b7adb0ec83458"}

图1-1
图1-1

在这里插入图片描述
图1-2

猜测base64的内容就是验证码,我们通过在线网站还原base64图片看一下,
通过转换工具是否能得到验证码图片【图1-3】
在这里插入图片描述
图1-3
那也就是说,验证码在每次刷新网页就会请求到,通过base64加载图片,验证图片后,与之携带的ctoken_id就生效,就能得到token,有了token后面的,兑换操作就能继续往下

😃😃第二步,保存验证码

通过python函数将base64转换为本地图片,该功能代码如下:

 		 base64转换图片-
         base64_data = base64.b64decode(base64_)
        
          将base64数据保存为图片
         with open('captcha.png', 'wb') as f:
             f.write(base64_data)

😃😃第三步,识别验证码

免费的验证码识别工具,我推荐DDDDocr,识别完成后通过验证即可

识别代码:
ocr = ddddocr.DdddOcr()
with open('captcha.png', 'rb') as f:
  img_bytes = f.read()
res = ocr.classification(img_bytes)
print('识别出的验证码为:' + res)

😃😃第四步,实现登录

通过抓包,我发现获取游戏昵称,也就是登录、鉴权的请求接口如此简单:

请求接口
http://com-sev.webapp.163.com/u5cdkey_query_uidinfo/api?img_auth=H8i&uid=123456&ctoken_id=58c24d6b9a1f43b3974306ae0b1e55c0&host_test=0&_=1689952803842&callback=jsonp

完整的请求响应结合刚刚分析的,再来总结下

请求参数说明
img_auth验证码内容
ctoken_id下发验证码的token_id
uid用户游戏id
响应参数说明
status状态
nick游戏昵称

那只要将上面的验证码识别出来配合uid就可以直接登录,并且获取到用户昵称以及认证过的token

😃兑换操作分析

在进行写代码前,我们进行流程分析,否则无从下手,这是蛋仔派对的兑换人口
在这里插入图片描述

请求URL请求方式
http://com-sev.webapp.163.com/u5cdkey_redeem/apiGET

将token,code,以及uid一起提交即可完成最后的操作,通过抓包我们将接口请求的思路,流程都梳理了一遍,现在就是动手的时候了,接下来我们通过cloud stdio在线IDE进行项目的开发

🍳实际操作

⭐注册Cloud Studio

注册Cloud Studio,这里注册和登录 Cloud Studio 非常方便,提供了下面三种注册方式:

  • 使用 CODING 账号授权注册/登录
  • 使用微信授权注册/登录 (本文使用方式)
  • 使用 GitHub 授权注册/登录

coding可对代码进行托管,微信授权注册后可以在这里绑定
在这里插入图片描述

⭐新建python项目(不选用模板)

⭐⭐创建项目

点击【新建模板】,再次点击【手动新建】
在这里插入图片描述

⭐⭐填写模板信息

在这里插入图片描述

⭐⭐选择环境镜像

选择python3.9,其他默认
在这里插入图片描述

⭐代码操作

⭐⭐获取验证码

在上面创建的空项目中,我们新建一个文件名叫:get_captcha.py
在这里插入图片描述
输入代码

import requests
import datetime
import time
headers = {
        'Host': 'com-sev.webapp.163.com',
        'Accept': '*/*',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
        'Referer': 'http://party.163.com/dh/m/',
    }
now = datetime.datetime.now()

    # 将当前时间转换为时间戳(秒级)
timestamp = time.mktime(now.timetuple())

    # 将时间戳转换为毫秒级时间戳
millisecond_timestamp = int(timestamp * 1000)
params = {
        'return_type': 'base64',
        '_': millisecond_timestamp,
        # 'callback': 'jsonp',
    }

response = requests.get('http://com-sev.webapp.163.com/get_apnt_auth_img', params=params,
                            headers=headers)
print(response.text)
result = response.json()

点击右上角运行后,显示base64图片代码和token_id,注意python中代码的格式对齐很严格
在这里插入图片描述

⭐⭐保存验证码

图片数据有了,应为要通过ocr识别,所以要将base64转换为图片保存在本地

'''
前面代码省略
'''
result = response.json()
if result['status']:
    base64_ = result['base64']
    ctoken_id = result['ctoken_id']
    print(base64_)
    print(ctoken_id)
    # base64转换图片-由于接口更换不需要
    base64_data = base64.b64decode(base64_)
    # 将base64数据保存为图片
    with open('captcha.png', 'wb') as f:
        f.write(base64_data)
else:
    print("验证码获取失败")
        

运行后本地产生一张图片
在这里插入图片描述
在这里插入图片描述

⭐⭐识别验证码

刚刚分析时,ddddocr,已经大概介绍过了,ddddocr是一个开源项目,托管在GitHub上。这使开发者可以自由地访问、使用和修改ddddocr的源代码,根据自己的需求进行定制和拓展。

ddddocr的主要功能和特点使其成为一个强大的双重数字识别工具,适用于各种需要识别双重数字的场景,例如票据识别、验证码识别、电子表格处理等。它的高准确性和灵活易用性使得开发者能够快速、准确地实现双重数字识别的需求,虽然免费版有很多缺点,但是识别今天的验证码够用了

'''
省略上面代码
注意,补上import ddddocr
'''
#5行即可识别
ocr = ddddocr.DdddOcr()
with open('captcha.png', 'rb') as f:
  img_bytes = f.read()
res = ocr.classification(img_bytes)
print('识别出的验证码为:' + res)

⭐⭐⭐ddddocr修复bug

图片数据有了,应为要通过ocr识别,所以要将base64转换为图片保存在本地
运行下看下识别效果,发现报错了
在这里插入图片描述
原来是刚刚的Ddddocr模块没装上,之前在顶部写入

import xxx

就会自动安装,但是现在不行,我们尝试手动安装吧

终端输入:

pip install ddddocr

等待安装完成即可
在这里插入图片描述

运行后报错:

➜ /workspace /root/.pyenv/versions/3.9.6/bin/python /workspace/index.py
Traceback (most recent call last):
File “/workspace/index.py”, line 6, in
res = ocr.classification(img_bytes)
File “/root/.pyenv/versions/3.9.6/lib/python3.9/site-packages/ddddocr/init.py”, line 1614, in classification
image = image.resize((int(image.size[0] * (64 / image.size[1])), 64), Image.ANTIALIAS).convert(‘L’)
AttributeError: module ‘PIL.Image’ has no attribute ‘ANTIALIAS’

问题出现在 Image.ANTIALIAS 属性上,这个属性在PIL库中已经不存在了。该错误提示与我之前提供的回答一致。从PIL 5.1.0版本开始,Image.ANTIALIAS 已经被替换为 Image.LANCZOS,因此导致你的代码在新版本的PIL库中出现错误。

要解决这个问题,你可以将 Image.ANTIALIAS 替换为 Image.LANCZOS,于是点击

在这里插入图片描述
跳转到__init__.py进行修改,不得不说cloud stdio 编辑器和真机环境没啥区别,自动化能力很强
在这里插入图片描述

修复后重新运行下,提取出的验证码与目标一致
在这里插入图片描述
在这里插入图片描述

⭐⭐接口鉴权

接下来我们编写一个接口请求用来通过验证,下方的代码运行后报错少了res,因为res是之前的验证码,接下来我们通过拼接使代码完整

#新建login.py
import requests
import datetime
import time
# 登录操作
headers = {
'Host': 'com-sev.webapp.163.com',
'Accept': '*/*',
'Connection': 'keep-alive',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Referer': 'http://party.163.com/dh/m/',
}
now = datetime.datetime.now()

# 将当前时间转换为时间戳(秒级)
timestamp = time.mktime(now.timetuple())

# 将时间戳转换为毫秒级时间戳
millisecond_timestamp = int(timestamp * 1000)
params = {
'img_auth': res,
'uid': '123456',
'ctoken_id': ctoken_id,
'host_test': '0',
'_': millisecond_timestamp,
# 'callback': 'jsonp3',
}

response = requests.get(
'http://com-sev.webapp.163.com/u5cdkey_query_uidinfo/api',
params=params,
headers=headers,
)
print(response.text)
resul = response.json()


重新拼接刚刚获取到的res,所以完整代码为:

#get_captcha.py
import requests
import datetime
import time
import base64
import ddddocr
headers = {
        'Host': 'com-sev.webapp.163.com',
        'Accept': '*/*',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
        'Referer': 'http://party.163.com/dh/m/',
    }
now = datetime.datetime.now()

    # 将当前时间转换为时间戳(秒级)
timestamp = time.mktime(now.timetuple())

    # 将时间戳转换为毫秒级时间戳
millisecond_timestamp = int(timestamp * 1000)
params = {
        'return_type': 'base64',
        '_': millisecond_timestamp,
        # 'callback': 'jsonp',
    }

response = requests.get('http://com-sev.webapp.163.com/get_apnt_auth_img', params=params,
                            headers=headers)
print(response.text)
result = response.json()
if result['status']:
    base64_ = result['base64']
    ctoken_id = result['ctoken_id']
    print(base64_)
    print(ctoken_id)
    # base64转换图片-由于接口更换不需要
    base64_data = base64.b64decode(base64_)
    # 将base64数据保存为图片
    with open('captcha.png', 'wb') as f:
        f.write(base64_data)

    ocr = ddddocr.DdddOcr()
    with open('captcha.png', 'rb') as f:
        img_bytes = f.read()
    res = ocr.classification(img_bytes)
    print('识别出的验证码为:' + res)
else:
    res=''
    print("验证码获取失败")

# 登录操作
headers = {
'Host': 'com-sev.webapp.163.com',
'Accept': '*/*',
'Connection': 'keep-alive',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Referer': 'http://party.163.com/dh/m/',
}
now = datetime.datetime.now()

# 将当前时间转换为时间戳(秒级)
timestamp = time.mktime(now.timetuple())

# 将时间戳转换为毫秒级时间戳
millisecond_timestamp = int(timestamp * 1000)
params = {
'img_auth': res,
'uid': '123456',
'ctoken_id': ctoken_id,
'host_test': '0',
'_': millisecond_timestamp,
# 'callback': 'jsonp3',
}

response = requests.get(
'http://com-sev.webapp.163.com/u5cdkey_query_uidinfo/api',
params=params,
headers=headers,
)
print(response.text)
resul = response.json()

测试效果,成功登录,由于验证码识别不是100%,所以你可能需要多试几次,直到登陆成功,可以进行下一个操作了,兑换操作!
在这里插入图片描述

⭐⭐福利码兑换

前面的各种参数我们已经拿到了,现在直接拿来用就OK,通过前面的抓包分析,我们发现,提交的参数就这三个

请求参数说明
code兑换码
uid个人游戏id
请求头说明
tokentoken_id

代码构造

# 兑换
import datetime
import time

import requests

headers = {
                        'Host': 'com-sev.webapp.163.com',
                        'Accept': '*/*',
                        'ctoken_id': 'sdsdsd',
                        'Connection': 'keep-alive',
                        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
                        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
                        'Referer': 'http://party.163.com/dh/m/',
                    }
now = datetime.datetime.now()

                    # 将当前时间转换为时间戳(秒级)
timestamp = time.mktime(now.timetuple())

                    # 将时间戳转换为毫秒级时间戳
millisecond_timestamp = int(timestamp * 1000)

params = {
                        'code':'123',
                        'uid': '123456',
                        'host_test': '0',
                        '_': millisecond_timestamp,
                        # 'callback': 'jsonp7',
                    }

response = requests.get('http://com-sev.webapp.163.com/u5cdkey_redeem/api', params=params,
                                            headers=headers)
print(response.json())

拼接后完整代码:

import requests
import datetime
import time
import base64
import ddddocr
headers = {
        'Host': 'com-sev.webapp.163.com',
        'Accept': '*/*',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
        'Referer': 'http://party.163.com/dh/m/',
    }
now = datetime.datetime.now()

    # 将当前时间转换为时间戳(秒级)
timestamp = time.mktime(now.timetuple())

    # 将时间戳转换为毫秒级时间戳
millisecond_timestamp = int(timestamp * 1000)
params = {
        'return_type': 'base64',
        '_': millisecond_timestamp,
        # 'callback': 'jsonp',
    }

response = requests.get('http://com-sev.webapp.163.com/get_apnt_auth_img', params=params,
                            headers=headers)
print(response.text)
result = response.json()
if result['status']:
    base64_ = result['base64']
    ctoken_id = result['ctoken_id']
    print(base64_)
    print(ctoken_id)
    # base64转换图片-由于接口更换不需要
    base64_data = base64.b64decode(base64_)
    # 将base64数据保存为图片
    with open('captcha.png', 'wb') as f:
        f.write(base64_data)

    ocr = ddddocr.DdddOcr()
    with open('captcha.png', 'rb') as f:
        img_bytes = f.read()
    res = ocr.classification(img_bytes)
    print('识别出的验证码为:' + res)
else:
    res=''
    print("验证码获取失败")

# 登录操作
headers = {
'Host': 'com-sev.webapp.163.com',
'Accept': '*/*',
'Connection': 'keep-alive',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Referer': 'http://party.163.com/dh/m/',
}
now = datetime.datetime.now()

# 将当前时间转换为时间戳(秒级)
timestamp = time.mktime(now.timetuple())

# 将时间戳转换为毫秒级时间戳
millisecond_timestamp = int(timestamp * 1000)
params = {
'img_auth': res,
'uid': '123456',
'ctoken_id': ctoken_id,
'host_test': '0',
'_': millisecond_timestamp,
# 'callback': 'jsonp3',
}

response = requests.get(
'http://com-sev.webapp.163.com/u5cdkey_query_uidinfo/api',
params=params,
headers=headers,
)
print(response.text)
resul = response.json()


# 兑换


headers = {
                        'Host': 'com-sev.webapp.163.com',
                        'Accept': '*/*',
                        'ctoken_id': 'sdsdsd',
                        'Connection': 'keep-alive',
                        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
                        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
                        'Referer': 'http://party.163.com/dh/m/',
                    }
now = datetime.datetime.now()

                    # 将当前时间转换为时间戳(秒级)
timestamp = time.mktime(now.timetuple())

                    # 将时间戳转换为毫秒级时间戳
millisecond_timestamp = int(timestamp * 1000)

params = {
                        'code':'123',
                        'uid': '123456',
                        'host_test': '0',
                        '_': millisecond_timestamp,
                        # 'callback': 'jsonp7',
                    }

response = requests.get('http://com-sev.webapp.163.com/u5cdkey_redeem/api', params=params,
                                            headers=headers)
print(response.json())

运行后结果
在这里插入图片描述

状态码说明
400兑换码不存在
未知兑换码已被使用
200兑换成功

⭐构建GUI视图

在这里插入图片描述

要想实现上面的效果,光有代码可是不够,于是我们需要通过可视化工具帮我们“画”一个界面

⭐⭐绘制可视化界面

接下来通过VB6画一个可视化界面
在这里插入图片描述

⭐⭐获得视图层代码

刷新窗体获得代码
在这里插入图片描述
这部分不懂得同学,可以看这个《Python tkinter快速可视化开发GUI界面指南:详细教程(附带工具)》

⭐⭐代码事件封装

在cloud stdio新建index.py,将下面我封装好的代码粘贴上去即可,由于ddddocr存在打包问题我这里有两个版本

#版本1-在线验证码识别
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import datetime
import json
import re
import time
from tkinter import messagebox

import requests

try:
    from tkinter import *
except ImportError:  #Python 2.x
    PythonVersion = 2
    from Tkinter import *
    from tkFont import Font
    from ttk import *
    #Usage:showinfo/warning/error,askquestion/okcancel/yesno/retrycancel
    from tkMessageBox import *
    #Usage:f=tkFileDialog.askopenfilename(initialdir='E:/Python')
    #import tkFileDialog
    #import tkSimpleDialog
else:  #Python 3.x
    PythonVersion = 3
    from tkinter.font import Font
    from tkinter.ttk import *
    from tkinter.messagebox import *
    #import tkinter.filedialog as tkFileDialog
    #import tkinter.simpledialog as tkSimpleDialog    #askstring()


def get_captcha():
    global ctoken_id
    global base_64_
    headers = {
        'Host': 'com-sev.webapp.163.com',
        'Accept': '*/*',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
        'Referer': 'http://party.163.com/dh/m/',
    }
    now = datetime.datetime.now()

    # 将当前时间转换为时间戳(秒级)
    timestamp = time.mktime(now.timetuple())

    # 将时间戳转换为毫秒级时间戳
    millisecond_timestamp = int(timestamp * 1000)
    params = {
        'return_type': 'base64',
        '_': millisecond_timestamp,
        # 'callback': 'jsonp',
    }

    response = requests.get('http://com-sev.webapp.163.com/get_apnt_auth_img', params=params,
                            headers=headers)
    # print(response.text)
    result = response.json()
    if result['status']:
        base64_ = result['base64']
        ctoken_id = result['ctoken_id']
        print(base64_)
        print(ctoken_id)
        ctoken_id=ctoken_id
        base_64_=base64_
        # base64转换图片-由于接口更换不需要
        # base64_data = base64.b64decode(base64_)
        #
        # # 将base64数据保存为图片
        # with open('captcha.png', 'wb') as f:
        #     f.write(base64_data)
    else:
        print("验证码获取失败")
        messagebox.showinfo(title='温馨提示', message='验证码获取失败')
class Application_ui(Frame):
    #这个类仅实现界面生成功能,具体事件处理代码在子类Application中。
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master.title('网易-蛋仔派对礼包码兑换工具-Q390983964')
        self.master.geometry('453x363')
        self.createWidgets()
        # self.Label6.config(text='0')
        # self.Label7.config(text='0')

    def createWidgets(self):
        self.top = self.winfo_toplevel()

        self.style = Style()

        self.style.configure('TCommand2.TButton', font=('宋体', 9))
        self.Command2 = Button(self.top, text='一键兑换', command=self.Command2_Cmd, style='TCommand2.TButton')
        self.Command2.place(relx=0.706, rely=0.793, relwidth=0.214, relheight=0.135)

        self.Text2Var = StringVar(value='')
        self.Text2 = Entry(self.top, textvariable=self.Text2Var, font=('宋体',9))
        self.Text2.place(relx=0.018, rely=0.419, relwidth=0.673, relheight=0.554)

        self.style.configure('TFrame1.TLabelframe', font=('宋体',9))
        self.style.configure('TFrame1.TLabelframe.Label', font=('宋体',9))
        self.Frame1 = LabelFrame(self.top, text='数据面板', style='TFrame1.TLabelframe')
        self.Frame1.place(relx=0.018, rely=0.132, relwidth=0.673, relheight=0.245)

        self.style.configure('TCommand1.TButton', font=('宋体',9))
        self.Command1 = Button(self.top, text='登录', command=self.Command1_Cmd, style='TCommand1.TButton')
        self.Command1.place(relx=0.477, rely=0.044, relwidth=0.091, relheight=0.069)

        self.Text1Var = StringVar(value='')
        self.Text1 = Entry(self.top, textvariable=self.Text1Var, font=('宋体',9))
        self.Text1.place(relx=0.141, rely=0.044, relwidth=0.232, relheight=0.051)


        self.style.configure('TLabel8.TLabel', anchor='w', font=('宋体', 9))
        self.Label8 = Label(self.top, text='日志区域', style='TLabel8.TLabel')
        self.Label8.place(relx=0.6, rely=0.066, relwidth=0.373, relheight=0.047)



        self.style.configure('TLabel1.TLabel', anchor='w', font=('宋体',9))
        self.Label1 = Label(self.top, text='游戏ID:', style='TLabel1.TLabel')
        self.Label1.place(relx=0.018, rely=0.044, relwidth=0.108, relheight=0.047)

        self.style.configure('TLabel7.TLabel', anchor='w', font=('宋体',9))
        self.Label7 = Label(self.Frame1, text='0', style='TLabel7.TLabel')
        self.Label7.place(relx=0.734, rely=0.629, relwidth=0.134, relheight=0.191)

        self.style.configure('TLabel6.TLabel', anchor='w', font=('宋体',9))
        self.Label6 = Label(self.Frame1, text='0', style='TLabel6.TLabel')
        self.Label6.place(relx=0.236, rely=0.629, relwidth=0.134, relheight=0.191)

        self.style.configure('TLabel5.TLabel', anchor='w', font=('宋体',9))
        self.Label5 = Label(self.Frame1, text='兑换失败:', style='TLabel5.TLabel')
        self.Label5.place(relx=0.498, rely=0.629, relwidth=0.213, relheight=0.191)

        self.style.configure('TLabel4.TLabel', anchor='w', font=('宋体',9))
        self.Label4 = Label(self.Frame1, text='兑换成功:', style='TLabel4.TLabel')
        self.Label4.place(relx=0.026, rely=0.629, relwidth=0.213, relheight=0.191)

        self.style.configure('TLabel3.TLabel', anchor='w', font=('宋体',9))
        self.Label3 = Label(self.Frame1, text='null', style='TLabel3.TLabel')
        self.Label3.place(relx=0.262, rely=0.27, relwidth=0.37, relheight=0.191)

        self.style.configure('TLabel2.TLabel', anchor='w', font=('宋体',9))
        self.Label2 = Label(self.Frame1, text='游戏昵称:', style='TLabel2.TLabel')
        self.Label2.place(relx=0.026, rely=0.27, relwidth=0.213, relheight=0.191)

        self.style.configure('TLabel9.TLabel', anchor='w', font=('宋体', 9))
        self.Label9 = Label(self.top, text='总计:', style='TLabel9.TLabel')
        self.Label9.place(relx=0.724, rely=0.419, relwidth=0.091, relheight=0.047)

        self.style.configure('TLabel10.TLabel', anchor='w', font=('宋体', 9))
        self.Label10 = Label(self.top, text='null', style='TLabel10.TLabel')
        self.Label10.place(relx=0.83, rely=0.419, relwidth=0.108, relheight=0.047)

        self.style.configure('TCommand3.TButton', font=('宋体', 9))
        self.Command3 = Button(self.top, text='兑换码统计', command=self.Command3_Cmd, style='TCommand3.TButton')
        self.Command3.place(relx=0.706, rely=0.551, relwidth=0.214, relheight=0.113)


class Application(Application_ui):
    #这个类实现具体的事件处理回调函数。界面生成代码在Application_ui中。
    def __init__(self, master=None):
        Application_ui.__init__(self, master)

    def Command2_Cmd(self, event=None):
        convert_fail=0
        convert_success=0
        # 一键兑换
        if login_state == 0:
            messagebox.showinfo(title='温馨提示', message='请先登录')
        else:
            if self.Text2Var.get() == '':
                self.Label8.config(text='兑换码不能为空...')
                messagebox.showinfo(title='温馨提示', message='兑换码不能为空')
            else:
                self.Label8.config(text='校验中...')
                text = self.Text2Var.get()
                pattern = r"【(卡\d+|通用)】(.*?)(?=【|$)"
                result = re.findall(pattern, text)
                # 总计
                self.Label10.config(text=len(result))
                for item in result:
                    time.sleep(1)
                    # item[1]
                    s=item[1]
                    ket_word = s.strip()
                    # 兑换

                    headers = {
                        'Host': 'com-sev.webapp.163.com',
                        'Accept': '*/*',
                        'Connection': 'keep-alive',
                        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
                        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
                        'Referer': 'http://party.163.com/dh/m/',
                    }
                    now = datetime.datetime.now()

                    # 将当前时间转换为时间戳(秒级)
                    timestamp = time.mktime(now.timetuple())

                    # 将时间戳转换为毫秒级时间戳
                    millisecond_timestamp = int(timestamp * 1000)

                    params = {
                        'code': ket_word,
                        'uid': username,
                        'host_test': '0',
                        '_': millisecond_timestamp,
                        # 'callback': 'jsonp7',
                    }

                    response = requests.get('http://com-sev.webapp.163.com/u5cdkey_redeem/api', params=params,
                                            headers=headers)
                    print(response.json())
                    result = response.json()
                    if result['status']:
                        self.Label8.config(text=result['msg'])
                        convert_success+=1
                        print(convert_success)
                        # self.Label6.config(text=convert_success)
                    else:
                        print(ket_word)
                        self.Label8.config(text=result['msg'])
                        convert_fail += 1
                        print(convert_fail)
                        # self.Label7.config(text=convert_fail)
                    self.Label6.config(text=convert_success)
                    self.Label7.config(text=convert_fail)
    def Command3_Cmd(self, event=None):
        self.Label8.config(text='正在统计兑换码!')
        print(f'输入框:{self.Text2Var.get()}')
        if self.Text2Var.get() == '':
            self.Label8.config(text='兑换码不能为空...')
            messagebox.showinfo(title='温馨提示', message='兑换码不能为空')
        else:
            self.Label8.config(text='校验中...')
            text =self.Text2Var.get()
            pattern = r"【(卡\d+|通用)】(.*?)(?=【|$)"
            result = re.findall(pattern, text)
            # 总计
            self.Label10.config(text=len(result))

    def Command1_Cmd(self, event=None):
        global username
        global login_state
        self.Label8.config(text='正在登陆...')
        url = 'http://web.taila.club/'
        response = requests.get(url)

        # print(response.json())  # 打印响应内容
        result = response.json()
        if result['code'] == 100:
            print(f'输入框:{self.Text1Var.get()}')
            if self.Text1Var.get() == '':
                self.Label8.config(text='用户id不能为空...')
                messagebox.showinfo(title='温馨提示', message='用户id不能为空')
            else:
                self.Label8.config(text='获取验证码中...')
                get_captcha()
                time.sleep(2)
                self.Label8.config(text='获取成功...')
                time.sleep(1)
                self.Label8.config(text='正在计算验证码...')
                #
                headers = {
                    'Host': 'com-sev.webapp.163.com',
                    'Accept': '*/*',
                    'Content-Type': 'application/json',
                    'Connection': 'keep-alive',
                    'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
                    'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
                    'Referer': 'http://party.163.com/dh/m/',
                }

                params = {
                    'image': base_64_,
                    'token': 'Ysmft8hCyULaAHbeIFuLFNeKy-hsZVjaw9dT6yKBM-Q',
                    'type': '10110',
                }

                response = requests.post('http://api.jfbym.com/api/YmServer/customApi', data=json.dumps(params),
                                         headers=headers)
                result = response.json()
                if result['code'] == 10000:
                    print("请求成功")
                    print(result['data']['data'])
                    res = result['data']['data']
                else:
                    print("验证码获取失败")
                    res = 'iii'

                #
                # 更换接口为在线的 ddddocr打包失败
                # ocr = ddddocr.DdddOcr()
                # with open('captcha.png', 'rb') as f:
                #     img_bytes = f.read()
                # res = ocr.classification(img_bytes)
                # print('识别出的验证码为:' + res)

                yzm_msg = f'识别出的验证码为:{res}'
                self.Label8.config(text=yzm_msg)
                # 登录操作
                headers = {
                    'Host': 'com-sev.webapp.163.com',
                    'Accept': '*/*',
                    'Connection': 'keep-alive',
                    'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
                    'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
                    'Referer': 'http://party.163.com/dh/m/',
                }
                now = datetime.datetime.now()

                # 将当前时间转换为时间戳(秒级)
                timestamp = time.mktime(now.timetuple())

                # 将时间戳转换为毫秒级时间戳
                millisecond_timestamp = int(timestamp * 1000)
                params = {
                    'img_auth': res,
                    'uid': self.Text1Var.get(),
                    'ctoken_id': ctoken_id,
                    'host_test': '0',
                    '_': millisecond_timestamp,
                    # 'callback': 'jsonp3',
                }

                response = requests.get(
                    'http://com-sev.webapp.163.com/u5cdkey_query_uidinfo/api',
                    params=params,
                    headers=headers,
                )
                print(response.text)
                resul = response.json()
                if resul['status']:
                    # 208146020
                    self.Label8.config(text='登陆成功...')
                    self.Label3.config(text=resul['nick'])
                    username = self.Text1Var.get()
                    login_state = 1
                else:
                    print("UID_ERROR")
                    self.Label8.config(text='登陆失败,请尝试')
                    self.Label3.config(text=resul['msg'])
                    self.Label8.config(text='请重新尝试登录')
                # 501验证码过期
        else:
            self.Label8.config(text='授权已被收回.')





if __name__ == "__main__":
    global login_state # 0未登录 1登录
    global ctoken_id  #token
    global base_64_
    global username  # 账号
    login_state=0
    top = Tk()
    Application(top).mainloop()


#版本2-本地验证码ddddocr识别
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import datetime
import json
import re
import time
import base64
import ddddocr
from tkinter import messagebox

import requests

try:
    from tkinter import *
except ImportError:  #Python 2.x
    PythonVersion = 2
    from Tkinter import *
    from tkFont import Font
    from ttk import *
    #Usage:showinfo/warning/error,askquestion/okcancel/yesno/retrycancel
    from tkMessageBox import *
    #Usage:f=tkFileDialog.askopenfilename(initialdir='E:/Python')
    #import tkFileDialog
    #import tkSimpleDialog
else:  #Python 3.x
    PythonVersion = 3
    from tkinter.font import Font
    from tkinter.ttk import *
    from tkinter.messagebox import *
    #import tkinter.filedialog as tkFileDialog
    #import tkinter.simpledialog as tkSimpleDialog    #askstring()


def get_captcha():
    global ctoken_id
    global base_64_
    headers = {
        'Host': 'com-sev.webapp.163.com',
        'Accept': '*/*',
        'Connection': 'keep-alive',
        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
        'Referer': 'http://party.163.com/dh/m/',
    }
    now = datetime.datetime.now()

    # 将当前时间转换为时间戳(秒级)
    timestamp = time.mktime(now.timetuple())

    # 将时间戳转换为毫秒级时间戳
    millisecond_timestamp = int(timestamp * 1000)
    params = {
        'return_type': 'base64',
        '_': millisecond_timestamp,
        # 'callback': 'jsonp',
    }

    response = requests.get('http://com-sev.webapp.163.com/get_apnt_auth_img', params=params,
                            headers=headers)
    # print(response.text)
    result = response.json()
    if result['status']:
        base64_ = result['base64']
        ctoken_id = result['ctoken_id']
        print(base64_)
        print(ctoken_id)
        ctoken_id=ctoken_id
        base_64_=base64_
        # base64转换图片-由于接口更换不需要
        base64_data = base64.b64decode(base64_)

        # 将base64数据保存为图片
        with open('captcha.png', 'wb') as f:
            f.write(base64_data)
    else:
        print("验证码获取失败")
        messagebox.showinfo(title='温馨提示', message='验证码获取失败')
class Application_ui(Frame):
    #这个类仅实现界面生成功能,具体事件处理代码在子类Application中。
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master.title('网易-蛋仔派对礼包码兑换工具-Q390983964')
        self.master.geometry('453x363')
        self.createWidgets()
        # self.Label6.config(text='0')
        # self.Label7.config(text='0')

    def createWidgets(self):
        self.top = self.winfo_toplevel()

        self.style = Style()

        self.style.configure('TCommand2.TButton', font=('宋体', 9))
        self.Command2 = Button(self.top, text='一键兑换', command=self.Command2_Cmd, style='TCommand2.TButton')
        self.Command2.place(relx=0.706, rely=0.793, relwidth=0.214, relheight=0.135)

        self.Text2Var = StringVar(value='')
        self.Text2 = Entry(self.top, textvariable=self.Text2Var, font=('宋体',9))
        self.Text2.place(relx=0.018, rely=0.419, relwidth=0.673, relheight=0.554)

        self.style.configure('TFrame1.TLabelframe', font=('宋体',9))
        self.style.configure('TFrame1.TLabelframe.Label', font=('宋体',9))
        self.Frame1 = LabelFrame(self.top, text='数据面板', style='TFrame1.TLabelframe')
        self.Frame1.place(relx=0.018, rely=0.132, relwidth=0.673, relheight=0.245)

        self.style.configure('TCommand1.TButton', font=('宋体',9))
        self.Command1 = Button(self.top, text='登录', command=self.Command1_Cmd, style='TCommand1.TButton')
        self.Command1.place(relx=0.477, rely=0.044, relwidth=0.091, relheight=0.069)

        self.Text1Var = StringVar(value='')
        self.Text1 = Entry(self.top, textvariable=self.Text1Var, font=('宋体',9))
        self.Text1.place(relx=0.141, rely=0.044, relwidth=0.232, relheight=0.051)


        self.style.configure('TLabel8.TLabel', anchor='w', font=('宋体', 9))
        self.Label8 = Label(self.top, text='日志区域', style='TLabel8.TLabel')
        self.Label8.place(relx=0.6, rely=0.066, relwidth=0.373, relheight=0.047)



        self.style.configure('TLabel1.TLabel', anchor='w', font=('宋体',9))
        self.Label1 = Label(self.top, text='游戏ID:', style='TLabel1.TLabel')
        self.Label1.place(relx=0.018, rely=0.044, relwidth=0.108, relheight=0.047)

        self.style.configure('TLabel7.TLabel', anchor='w', font=('宋体',9))
        self.Label7 = Label(self.Frame1, text='0', style='TLabel7.TLabel')
        self.Label7.place(relx=0.734, rely=0.629, relwidth=0.134, relheight=0.191)

        self.style.configure('TLabel6.TLabel', anchor='w', font=('宋体',9))
        self.Label6 = Label(self.Frame1, text='0', style='TLabel6.TLabel')
        self.Label6.place(relx=0.236, rely=0.629, relwidth=0.134, relheight=0.191)

        self.style.configure('TLabel5.TLabel', anchor='w', font=('宋体',9))
        self.Label5 = Label(self.Frame1, text='兑换失败:', style='TLabel5.TLabel')
        self.Label5.place(relx=0.498, rely=0.629, relwidth=0.213, relheight=0.191)

        self.style.configure('TLabel4.TLabel', anchor='w', font=('宋体',9))
        self.Label4 = Label(self.Frame1, text='兑换成功:', style='TLabel4.TLabel')
        self.Label4.place(relx=0.026, rely=0.629, relwidth=0.213, relheight=0.191)

        self.style.configure('TLabel3.TLabel', anchor='w', font=('宋体',9))
        self.Label3 = Label(self.Frame1, text='null', style='TLabel3.TLabel')
        self.Label3.place(relx=0.262, rely=0.27, relwidth=0.37, relheight=0.191)

        self.style.configure('TLabel2.TLabel', anchor='w', font=('宋体',9))
        self.Label2 = Label(self.Frame1, text='游戏昵称:', style='TLabel2.TLabel')
        self.Label2.place(relx=0.026, rely=0.27, relwidth=0.213, relheight=0.191)

        self.style.configure('TLabel9.TLabel', anchor='w', font=('宋体', 9))
        self.Label9 = Label(self.top, text='总计:', style='TLabel9.TLabel')
        self.Label9.place(relx=0.724, rely=0.419, relwidth=0.091, relheight=0.047)

        self.style.configure('TLabel10.TLabel', anchor='w', font=('宋体', 9))
        self.Label10 = Label(self.top, text='null', style='TLabel10.TLabel')
        self.Label10.place(relx=0.83, rely=0.419, relwidth=0.108, relheight=0.047)

        self.style.configure('TCommand3.TButton', font=('宋体', 9))
        self.Command3 = Button(self.top, text='兑换码统计', command=self.Command3_Cmd, style='TCommand3.TButton')
        self.Command3.place(relx=0.706, rely=0.551, relwidth=0.214, relheight=0.113)


class Application(Application_ui):
    #这个类实现具体的事件处理回调函数。界面生成代码在Application_ui中。
    def __init__(self, master=None):
        Application_ui.__init__(self, master)

    def Command2_Cmd(self, event=None):
        convert_fail=0
        convert_success=0
        # 一键兑换
        if login_state == 0:
            messagebox.showinfo(title='温馨提示', message='请先登录')
        else:
            if self.Text2Var.get() == '':
                self.Label8.config(text='兑换码不能为空...')
                messagebox.showinfo(title='温馨提示', message='兑换码不能为空')
            else:
                self.Label8.config(text='校验中...')
                text = self.Text2Var.get()
                pattern = r"【(卡\d+|通用)】(.*?)(?=【|$)"
                result = re.findall(pattern, text)
                # 总计
                self.Label10.config(text=len(result))
                for item in result:
                    time.sleep(1)
                    # item[1]
                    s=item[1]
                    ket_word = s.strip()
                    # 兑换

                    headers = {
                        'Host': 'com-sev.webapp.163.com',
                        'Accept': '*/*',
                        'Connection': 'keep-alive',
                        'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
                        'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
                        'Referer': 'http://party.163.com/dh/m/',
                    }
                    now = datetime.datetime.now()

                    # 将当前时间转换为时间戳(秒级)
                    timestamp = time.mktime(now.timetuple())

                    # 将时间戳转换为毫秒级时间戳
                    millisecond_timestamp = int(timestamp * 1000)

                    params = {
                        'code': ket_word,
                        'uid': username,
                        'host_test': '0',
                        '_': millisecond_timestamp,
                        # 'callback': 'jsonp7',
                    }

                    response = requests.get('http://com-sev.webapp.163.com/u5cdkey_redeem/api', params=params,
                                            headers=headers)
                    print(response.json())
                    result = response.json()
                    if result['status']:
                        self.Label8.config(text=result['msg'])
                        convert_success+=1
                        print(convert_success)
                        # self.Label6.config(text=convert_success)
                    else:
                        print(ket_word)
                        self.Label8.config(text=result['msg'])
                        convert_fail += 1
                        print(convert_fail)
                        # self.Label7.config(text=convert_fail)
                    self.Label6.config(text=convert_success)
                    self.Label7.config(text=convert_fail)
    def Command3_Cmd(self, event=None):
        self.Label8.config(text='正在统计兑换码!')
        print(f'输入框:{self.Text2Var.get()}')
        if self.Text2Var.get() == '':
            self.Label8.config(text='兑换码不能为空...')
            messagebox.showinfo(title='温馨提示', message='兑换码不能为空')
        else:
            self.Label8.config(text='校验中...')
            text =self.Text2Var.get()
            pattern = r"【(卡\d+|通用)】(.*?)(?=【|$)"
            result = re.findall(pattern, text)
            # 总计
            self.Label10.config(text=len(result))

    def Command1_Cmd(self, event=None):
        global username
        global login_state
        self.Label8.config(text='正在登陆...')
        url = 'http://web.taila.club/'
        response = requests.get(url)

        # print(response.json())  # 打印响应内容
        result = response.json()
        if result['code'] == 100:
            print(f'输入框:{self.Text1Var.get()}')
            if self.Text1Var.get() == '':
                self.Label8.config(text='用户id不能为空...')
                messagebox.showinfo(title='温馨提示', message='用户id不能为空')
            else:
                self.Label8.config(text='获取验证码中...')
                get_captcha()
                time.sleep(2)
                self.Label8.config(text='获取成功...')
                time.sleep(1)
                self.Label8.config(text='正在计算验证码...')
                #
                # headers = {
                #     'Host': 'com-sev.webapp.163.com',
                #     'Accept': '*/*',
                #     'Content-Type': 'application/json',
                #     'Connection': 'keep-alive',
                #     'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
                #     'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
                #     'Referer': 'http://party.163.com/dh/m/',
                # }
                #
                # params = {
                #     'image': base_64_,
                #     'token': 'Ysmft8hCyULaAHbeIFuLFNeKy-hsZVjaw9dT6yKBM-Q',
                #     'type': '10110',
                # }
                #
                # response = requests.post('http://api.jfbym.com/api/YmServer/customApi', data=json.dumps(params),
                #                          headers=headers)
                # result = response.json()
                # if result['code'] == 10000:
                #     print("请求成功")
                #     print(result['data']['data'])
                #     res = result['data']['data']
                # else:
                #     print("验证码获取失败")
                #     res = 'iii'

                #
                # 更换接口为在线的 ddddocr打包失败
                ocr = ddddocr.DdddOcr()
                with open('captcha.png', 'rb') as f:
                    img_bytes = f.read()
                res = ocr.classification(img_bytes)
                print('识别出的验证码为:' + res)

                yzm_msg = f'识别出的验证码为:{res}'
                self.Label8.config(text=yzm_msg)
                # 登录操作
                headers = {
                    'Host': 'com-sev.webapp.163.com',
                    'Accept': '*/*',
                    'Connection': 'keep-alive',
                    'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5.1 Mobile/15E148 Safari/604.1',
                    'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
                    'Referer': 'http://party.163.com/dh/m/',
                }
                now = datetime.datetime.now()

                # 将当前时间转换为时间戳(秒级)
                timestamp = time.mktime(now.timetuple())

                # 将时间戳转换为毫秒级时间戳
                millisecond_timestamp = int(timestamp * 1000)
                params = {
                    'img_auth': res,
                    'uid': self.Text1Var.get(),
                    'ctoken_id': ctoken_id,
                    'host_test': '0',
                    '_': millisecond_timestamp,
                    # 'callback': 'jsonp3',
                }

                response = requests.get(
                    'http://com-sev.webapp.163.com/u5cdkey_query_uidinfo/api',
                    params=params,
                    headers=headers,
                )
                print(response.text)
                resul = response.json()
                if resul['status']:
                    # 208146020
                    self.Label8.config(text='登陆成功...')
                    self.Label3.config(text=resul['nick'])
                    username = self.Text1Var.get()
                    login_state = 1
                else:
                    print("UID_ERROR")
                    self.Label8.config(text='登陆失败,请尝试')
                    self.Label3.config(text=resul['msg'])
                    self.Label8.config(text='请重新尝试登录')
                # 501验证码过期
        else:
            self.Label8.config(text='授权已被收回.')





if __name__ == "__main__":
    global login_state # 0未登录 1登录
    global ctoken_id  #token
    global base_64_
    global username  # 账号
    login_state=0
    top = Tk()
    Application(top).mainloop()


⭐⭐软件打包

相信能到这里的同学,应该都在cloud stdio中尝试运行过,可惜报错了
在这里插入图片描述
这个错误提示说明在你的代码中使用了Tkinter图形界面,但是当前环境下没有可用的图形显示。这通常是因为你正在使用一个没有图形界面的环境,比如SSH远程连接或者在不支持图形界面的服务器上运行脚本,所以在线编辑器目前运行不了,但是我们可以打包下载到本地环境运行

在cloud stdio终端输入

clear

进行日志清空

安装pyinstaller进行打包

pip install pyinstaller 

在这里插入图片描述
模块安装完后,进行打包操作

pyinstaller -D -w index.py

在这里插入图片描述

打包完成后下载即可
在这里插入图片描述

本地运行
在这里插入图片描述

⭐总结

本次项目用到了在线IDE:Cloud stdio,不得不说真的很方便,我经过这次体验总结出几个优缺点

Cloud stdio优点缺点
Python环境-模块自动安装模块大的模块需要手动安装,例如:request自动安装但是Ddddocr需要手动命令安装
Python环境-共享库资源齐全,下载速度快,版本不支持也会提醒升级pip打包文件时需要的依赖由于环境问题无法拉取打包,无法找到所需的共享库文件来支持打包,其中包括libpython3.9m.so等文件
Python环境-可视化可视化界面运行不了,会提示_tkinter.TclError: couldn't connect to display ":0"
界面整洁清爽,容易快速上手,可选择基础框架快速开发新建工作空间不能使用本地代码进行上传只能从仓库拉取
费用标准版包月300有点贵

建议:

优化虚拟模块的拉取方式,使得tk项目可以打包,对一些可视化的容错处理,报错信息再优化,其他做的真不错,可能后面可视化建议有点不切实际,如果价格能够下降一点会更受青睐,以上是我个人的建议。

🍋如果你喜欢爬虫相关,请看下面
《记一次云之家签到抓包》
《记一次视频抓包m3u8解密过程》
《抓包部分软件时无网络+过代理检测 解决办法 安卓黄鸟httpcanary+vmos》
《Python】记录抓包分析自动领取芝麻HTTP每日免费IP(成品+教程)》
《某课抓包视频 安卓手机:黄鸟+某课app+VirtualXposed虚拟框架》

推荐专栏:

《Python爬虫脚本项目实战》

该专栏往期文章:
《【Python爬虫项目实战一】获取Chatgpt3.5免费接口文末付代码(过Authorization认证)》

🥦如果感觉看完文章还不过瘾,欢迎查看我的其它专栏
🥦作者对python有很大的兴趣,完成过很多独立的项目:例如滇医通等等脚本,但是由于版权的原因下架了,爬虫这一类审核比较严谨,稍有不慎就侵权违规了,所以在保证质量的同时会对文章进行筛选

如果您对爬虫感兴趣请收藏或者订阅该专栏哦《Python爬虫脚本项目实战》,如果你有项目欢迎联系我,我会同步教程到本专栏!

🚀Python爬虫项目实战系列文章!!
⭐⭐欢迎订阅⭐⭐

【Python爬虫项目实战一】获取Chatgpt3.5免费接口文末付代码(过Authorization认证)
【Python爬虫项目实战二】Chatgpt还原验证算法-解密某宝伪知网数据接口

⭐⭐欢迎订阅⭐⭐
在这里插入图片描述

Python爬虫脚本项目实战
在这里插入图片描述

完整项目:https://e.coding.net/coding-damowang/danzaipaiduiduihuanmagongju/workspace.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/43236.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

山西电力市场日前价格预测【2023-07-24】

日前价格预测 预测明日(2023-07-24)山西电力市场全天平均日前电价为338.25元/MWh。其中,最高日前电价为377.59元/MWh,预计出现在20: 30。最低日前电价为283.56元/MWh,预计出现在13: 30。 价差方向预测 1:实…

LiveNVR监控流媒体Onvif/RTSP功能-支持无人机、IPC等设备RTMP推流转码分发H5无插件播放也支持GB28181输出

LiveNVR支持无人机、IPC等设备RTMP推流转码分发H5无插件播放也支持GB28181输出 1、无人机推流转国标2、获取RTMP推流地址2.1、RTMP推流地址格式2.2、推流地址示例 2、设备RTMP推流3、配置拉转RTMP3.1、直播流地址格式3.2、直播流地地址示例3.3、通道配置直播流地址 4、配置级联…

精准测试之分布式调用链底层逻辑

目录 前言: ⼀、分布式调⽤链系统概述 分布式架构所带来的问题 分布式链路监控的作用 ⼆、调用链系统的演进 链路监控系统列表 三、调用链系统的底层实现逻辑 调用链系统的本质 调用链基本元素 事件捕捉 事件串联 事件的开始与结束 上传 四、Span 内容…

Stable Diffusion如何生成高质量的图-prompt写法介绍

文章目录 Stable Diffusion使用尝试下效果prompt的编写技巧prompt 和 negative promptPrompt格式Prompt规则细节优化Guidance Scale 总结 Stable Diffusion Stable Diffusion是一个开源的图像生成AI系统,由Anthropic公司开发。它基于 Transformer模型架构,可以通过文字描述生成…

WAIC2023:图像内容安全黑科技助力可信AI发展

目录 0 写在前面1 AI图像篡改检测2 生成式图像鉴别2.1 主干特征提取通道2.2 注意力模块2.3 纹理增强模块 3 OCR对抗攻击4 助力可信AI向善发展总结 0 写在前面 2023世界人工智能大会(WAIC)已圆满结束,恰逢全球大模型和生成式人工智能蓬勃兴起之时,今年参…

Two Days wpf 分享 分页组件

迟来的wpf分享。 目录 一、序言 二、前期准备 三、前端界面 四、后台代码部分 1、先定义些变量后面使用 2、先是按钮事件代码。 首页按钮 上一页按钮 下一页按钮 末尾按钮 画每页显示等数据 每页显示多少条 判断是否为数字的事件 分页数字的点击触发事件 跳转到…

jmeter常用的提取器(正则表达式和JSON提取器)

jmeter常用的后置处理器有两种提取数据: 1、JSON提取器 获取后可以将变量token引用到其他所需要的地方 (正则表达式和JSON提取器):2023接口自动化测试框架必会两大神器:正则提取器和Jsonpath提取器_哔哩哔哩_bilibilihttps://www.bilibili.…

JVM运行时数据区——堆内的区域分布

1.堆内的区域分布 堆是运行时数据区最大的一块区域,主要用来存放对象,堆是所有线程公用的,在JVM启动时就被创建,堆的空间是可以调整的,是GC(垃圾回收)的重点区域。 堆的内存空间分区:新生代老年代 新生代…

Rust vs Go:常用语法对比(三)

题图来自When to use Rust and when to use Go[1] 41. Reverse a string 反转字符串 package mainimport "fmt"func Reverse(s string) string { runes : []rune(s) for i, j : 0, len(runes)-1; i < j; i, j i1, j-1 { runes[i], runes[j] runes[j], runes[i]…

【SQL应知应会】表分区(五)• MySQL版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 分区表 • MySQL版 前言一、分区表1.非分区表2.分区…

【论文】基于GANs的图像文字擦除 ——2010.EraseNet: End-to-End Text Removal in the Wild(已开源)

pytorch官方代码&#xff1a;https://github.com/lcy0604/EraseNet 论文&#xff1a;2010.EraseNet: End-to-End Text Removal in the Wild 网盘提取码&#xff1a;0719 一、图片文字去除效果 图10 SCUT-EnsText 真实数据集的去除 第一列原图带文字、第二列为去除后的标签&a…

RocketMQ分布式事务 -> 最终一致性实现

文章目录 前言事务消息场景代码示例订单服务事务日志表TransactionMQProducerOrderTransactionListener业务实现类调用总结 积分服务积分记录表消费者启动消费者监听器增加积分幂等性消费消费异常 前言 分布式事务的问题常在业务与面试中被提及, 近日摸鱼看到这篇文章, 阐述的…

认识主被动无人机遥感数据、预处理无人机遥感数据、定量估算农林植被关键性状、期刊论文插图精细制作与Appdesigner应用开发

目录 第一章、认识主被动无人机遥感数据 第二章、预处理无人机遥感数据 第三章、定量估算农林植被关键性状 第四章、期刊论文插图精细制作与Appdesigner应用开发 更多推荐 遥感技术作为一种空间大数据手段&#xff0c;能够从多时、多维、多地等角度&#xff0c;获取大量的…

Spring 能解决所有循环依赖吗?

以下内容基于 Spring6.0.4。 看了上篇文章的小伙伴&#xff0c;对于 Spring 解决循环依赖的思路应该有一个大致了解了&#xff0c;今天我们再来看一看&#xff0c;按照上篇文章介绍的思路&#xff0c;有哪些循环依赖 Spring 处理不了。 严格来说&#xff0c;其实也不是解决不了…

PoseiSwap 即将开启 POSE 单币质押,治理体系将全面运行

PoseiSwap 是目前行业首个将支持 RWA 资产交易的 DEX&#xff0c;其构建在 Nautilus Chain 上&#xff0c;并通过模块化的形式单独构建了 zk-Rollup 应用层&#xff0c;具备并行化运行、隐私特性&#xff0c;并从 Cosmos、Celestia、Eclipse 等 Layer0 设施中获得高度可组合性、…

MySQL 中NULL和空值的区别

MySQL 中NULL和空值的区别&#xff1f; 简介NULL也就是在字段中存储NULL值&#xff0c;空值也就是字段中存储空字符(’’)。区别 1、空值不占空间&#xff0c;NULL值占空间。当字段不为NULL时&#xff0c;也可以插入空值。 2、当使用 IS NOT NULL 或者 IS NULL 时&#xff0…

JDK、JRE、JVM三者之间的关系

总结 JDK包含JRE&#xff0c;JRE包含JVM。 JDK (Java Development Kit)----Java开发工具包&#xff0c;用于Java程序的开发。 JRE (Java Runtime Environment)----Java运行时环境&#xff0c;只能运行.class文件&#xff0c;不能编译。 JVM (Java Virtual Machine)----Java虚拟…

21matlab数据分析牛顿插值(matlab程序)

1.简述 一、牛顿插值法原理 1.牛顿插值多项式   定义牛顿插值多项式为&#xff1a; N n ( x ) a 0 a 1 ( x − x 0 ) a 2 ( x − x 0 ) ( x − x 1 ) ⋯ a n ( x − x 0 ) ( x − x 1 ) ⋯ ( x − x n − 1 ) N_n\left(x\right)a_0a_1\left(x-x_0\right)a_2\left(x-x_0\…

AI时代带来的图片造假危机,该如何解决

一、前言 当今&#xff0c;图片造假问题非常泛滥&#xff0c;已经成为现代社会中一个严峻的问题。随着AI技术不断的发展&#xff0c;人们可以轻松地通过图像编辑和AI智能生成来篡改和伪造图片&#xff0c;使其看起来真实而难以辨别&#xff0c;之前就看到过一对硕士夫妻为了骗…

子网划分路由网卡安全组

1."IPv4 CIDR" "IPv4 CIDR" 是与互联网协议地址&#xff08;IP address&#xff09;和网络的子网划分有关的概念。 - "IPv4" 代表 "Internet Protocol version 4"&#xff0c;也就是第四版互联网协议&#xff0c;这是互联网上最广泛使…