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

目录

🍳前言

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】,这是抓包响应结构:

python 复制代码
{"status": true, "base64": "/9j*****Q==", "ctoken_id": "e8814dbbec8348ea8b0b7adb0ec83458"}

图1-1

图1-2

猜测base64的内容就是验证码,我们通过在线网站还原base64图片看一下,

通过转换工具是否能得到验证码图片【图1-3】

图1-3

那也就是说,验证码在每次刷新网页就会请求到,通过base64加载图片,验证图片后,与之携带的ctoken_id就生效,就能得到token,有了token后面的,兑换操作就能继续往下

😃😃第二步,保存验证码

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

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

😃😃第三步,识别验证码

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

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

😃😃第四步,实现登录

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

python 复制代码
请求接口
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/api GET

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

🍳实际操作

⭐注册Cloud Studio

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

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

coding可对代码进行托管,微信授权注册后可以在这里绑定

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

⭐⭐创建项目

点击【新建模板】,再次点击【手动新建】

⭐⭐填写模板信息

⭐⭐选择环境镜像

选择python3.9,其他默认

⭐代码操作

⭐⭐获取验证码

在上面创建的空项目中,我们新建一个文件名叫:get_captcha.py

输入代码

python 复制代码
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转换为图片保存在本地

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

python 复制代码
'''
省略上面代码
注意,补上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模块没装上,之前在顶部写入

python 复制代码
import xxx

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

终端输入:

python 复制代码
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是之前的验证码,接下来我们通过拼接使代码完整

python 复制代码
#新建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,所以完整代码为:

python 复制代码
#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
请求头 说明
token token_id

代码构造

python 复制代码
# 兑换
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())

拼接后完整代码:

python 复制代码
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存在打包问题我这里有两个版本

python 复制代码
#版本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()
python 复制代码
#版本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终端输入

python 复制代码
clear

进行日志清空

安装pyinstaller进行打包

python 复制代码
pip install pyinstaller 

模块安装完后,进行打包操作

python 复制代码
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

相关推荐
HaoHao_0102 小时前
VMware 的 AWS
大数据·服务器·数据库·云计算·aws·云服务器
费3 小时前
1、云计算
网络·云计算
xidianjiapei0016 小时前
优化性能:高性能云计算的虚拟化技术
性能优化·云计算·虚拟化·高性能计算
云上的阿七1 天前
云计算如何与物联网(IoT)结合?
物联网·云计算
古猫先生1 天前
浅析云场景SSD实时迁移技术
服务器·科技·云计算
佛州小李哥2 天前
在亚马逊云科技上用AI提示词优化功能写出漂亮提示词(上)
人工智能·科技·ai·语言模型·云计算·aws·亚马逊云科技
云和恩墨2 天前
云计算、AI与国产化浪潮下DBA职业之路风云变幻,如何谋破局启新途?
数据库·人工智能·云计算·dba
努力的小T2 天前
基于 Bash 脚本的系统信息定时收集方案
linux·运维·服务器·网络·云计算·bash
Linux运维老纪2 天前
分布式存储的技术选型之HDFS、Ceph、MinIO对比
大数据·分布式·ceph·hdfs·云原生·云计算·运维开发
monkey222 天前
AWS S3的费用优化
云计算·aws