Tkinter和selenium结合实现登录UC后台,最后打包成exe

2024-06-24 09:08

本文主要是介绍Tkinter和selenium结合实现登录UC后台,最后打包成exe,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

主要实现的功能:小号模式自动登录UC阿里汇川广告后台,屏蔽账号密码输入
主要用的技术:用Tkinter展示所有的广告账号界面,使用selenium控制谷歌浏览器,打开阿里汇川登录页,登录汇川后台。
第一次写,遇到的坑比较多,三天,搞定。给自己一个棒棒~☺️

import Tkinter as tk  
import os
import sys
import requests
from selenium import webdriver
import base64
from PIL import Image, ImageTk
import mathpath = os.path.split(os.path.realpath(__file__))[0] + os.sepclass showCode(tk.Toplevel):def __init__(self):# super().__init__()tk.Toplevel.__init__(self)self.title('请输入验证码')self.wm_attributes('-topmost',1)# 弹窗界面self.setup_UI()def setup_UI(self):# from PIL import Image# im = Image.open(path + 'code/code.gif')# im.show()self._inputCode = tk.StringVar() # 将此处的验证码放置到类中,直接获取该值无法获取frame = tk.Frame(self)  #初始化一个框架frame.pack()im=Image.open(path  + "/code/code.gif")  self.photo=ImageTk.PhotoImage(im)  cv = tk.Canvas(frame)  cv.pack(side='top',fill='both', expand='false',padx=20,pady=20)  cv.create_image(0, 0, image=self.photo, anchor='nw')  # im=Image.open(path + 'code/code.gif')# img=ImageTk.PhotoImage(im)# imLabel=tk.Label(frame,image=img).pack()# 显示图片e1 = tk.Entry(frame,width=10,textvariable=self._inputCode).pack(anchor='w')tk.Button(frame,text='确定',command=self.setCode).pack(anchor='w')#点击确定将验证码赋值给主窗口  def setCode(self):self.inputCode = self._inputCode.get()self.destroy() # 销毁窗口# 主窗
class MyApp(tk.Tk):def __init__(self):global path# super().__init__()tk.Tk.__init__(self)#self.pack() # 若继承 tk.Frame ,此句必须有!self.title('UC账号管家')self.geometry('1000x600')self.iconbitmap(default='code/logo.ico')  # 加图标# 获取所有账号self.getAccountsFirst()    # 调起程序界面self.setupUI()# 获取所有的投放账号def getAccountsFirst(self):f = open(path + 'code/account.log')content = f.read()f.close()#解密账号_account = base64.b64decode(content).replace(' ', '').split("\n")__account = []for i in range(len(_account)):__account.append(_account[i].split(","))# self.account[i] = _account[i].split(",")#将账号赋值给账号界面self.accounts = __account#拉起账号界面def setupUI(self):def callback():argAccount = var.get()for account in self.accounts:if(account[0].decode('utf-8') == argAccount):# 此时做登录操作self.login(account[0],account[1])row1 = tk.LabelFrame(self)var = tk.StringVar()group=tk.LabelFrame(row1,text='选择要登录的账号').pack(padx=100)   # 基于root 制定一个框架 . count = 0row = 1for name,pwd in self.accounts:column = int(math.fmod(count,5))if(row * 5 == count):row = row + 1b = tk.Radiobutton(group,text=name,variable=var,value=name,indicatoron=0,padx=30,pady=3,command=callback)b.grid(row=row,column=column)count = count + 1# b.pack(anchor="w")label = tk.Label(row1)label.pack()def login(self,username,pwd):#开始登陆login_url = 'https://e.uc.cn/'headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) ''Chrome/58.0.3029.110 Safari/537.36'}options = webdriver.ChromeOptions()options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors"])options.add_argument('disable-infobars')driver = webdriver.Chrome(chrome_options=options)# options.binary_location = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"# driver.chrome_driver_binary = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"# driver = webdriver.Chrome()driver.delete_all_cookies()driver.get("https://e.uc.cn/sso/static/pages/hcsso.html?authorizeUrl=http%3A%2F%2Fe.uc.cn%2Fsso%2Fv1%2Fauthorize%3Fresponse_type%3Dcode%26scope%3Dopenid%26client_id%3DeyJjdHkiOiJKV1QiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTEyOEtXIn0.PYe1Zfthswo5iITZVGBkn5hCfdzyuQAkXWPE7VAO0eAuRNEzikoQgQ.3g8Cf2JZ2D8bhKdKlgaHGw.-56UrnfHvZPoryCii7MPSvoBUlnacryxYxBqQBLUQe3k_XJ1j3Trv-Io9JK9Pg3CyFbslM281pe8MsNGjvIfPUT7Z_Vc0N_0t_bCp3Lp4H0eJ3YODXapXgMX2qYROw1uWCbb8FcWpa37HyySgjsaOHIiDVkwmb3I_flywaJu5Tavbp09nwirOg-AJ8unie4nQXt9XqA5Dpq9F5qv36TFGVKRUbTMzvA8XGjUpE1ExL5oodpxfh8FfUfBLvF69PgjHwJiijrC702X5VHx0Og949xnmIX4znCbJ3MPUDjPwtS92IxGYypjWDTi4bfWYZYl8iPVoMbZCCz--QrmH1FUjznu6YmVavmKXasvHg6qI9Gpn5hnv--9rPp0CJgpJg_7DLyxr4D7jOj2Ju7gXGNPKqsoqP_GT1zsa1mkUZbeMSLYQVZJPwO6HLcpyZG-zH1_fz70IgIxACHBxky2V3P9WgUaExKys-e_8zawHxWpbyTl1DZlg7v1razzzrwgteHmpoJxyRUt_Gs7WQyYlCrgLrhVWEF7JKTy9MJFeepuGg8GWyzUtu86yRkIkDDL726B4J_sa779JzfutyZtVBAj36BuSj_EnvFsNau13vJ23Nyc3wm8TT8QS6xD6vrKRHWYCp7trDHcInlIczi7gnVth2c_RstjKeE8wcIPN1a1-4wkwIiUAkrnx_y2EaUECHp5vHITjbpBD1rPzZwKZT8Mlw.9hgjcRYoM3FgvXVF7YOgIw%26redirect_uri%3Dhttps%3A%2F%2Fe.uc.cn%2Fuc%2Fsso_auth_code%26target_url%3Dhttp%3A%2F%2Fe.uc.cn%2Fuc%2F%3FisFromPortal%3D0")# 将所有的cookie清除driver.delete_all_cookies()#重新获取验证码并且将cookie写入浏览器cookies = self.getCode()for cok in cookies:driver.add_cookie({'name':cok,'value':cookies[cok]})# 弹窗code = self.ask_inputCode()userName = driver.find_element_by_id('username')password = driver.find_element_by_id('password')captchaCode = driver.find_element_by_name('captchaCode')userName.clear()userName.send_keys(username.decode('utf-8'))password.clear()password.send_keys(pwd.decode('utf-8'))captchaCode.send_keys(code.decode('utf-8'))submit = driver.find_element_by_class_name('js-hc-loginBtn')submit.click()def ask_inputCode(self):inputOjb = showCode()self.wait_window(inputOjb) # 这一句很重要!!!return inputOjb.inputCodedef getCode(self):global pathimg_src = "https://e.uc.cn/sso/auth.jpg"r = requests.get(img_src)r.raise_for_status()with open(path + 'code/code.gif',"wb") as f: #开始写文件,wb代表写二进制文件f.write(r.content)f.close()f.close()cookies = requests.utils.dict_from_cookiejar(r.cookies)return cookiesif __name__ == '__main__':app = MyApp()app.mainloop()

关于环境:

我是在mac里面先写完,然后最后因为要编译成exe,所以必须在window里面重新再搭建环境。
遇到的问题:
问题一、
同样是使用Tkinter,环境py27
mac中 import tkinter as tk 是没问题的

在window中使用    import tkinter as tk  报 ImportError:No module named tkinter

解决办法:原来一直以为是没有装tkinter,因为在mac里面使用(
mac安装Tkinter库brew install homebrew/dupes/tcl-tk)重新过tkinter,以为window也要重新搞一遍
后来发现用法用错了。在window中py2.7 要使用

import Tkinter as tk

问题二、

关于代码

问题一、最开始没有使用类的方式,所有的方法都放在一个文件中,然后在弹窗将输入的值返回给主界面,一直返回不回去。如果要设置的参数个数超过两个,那么tkinter提供的标准窗口就处理不了了。怎样将自定义窗口中的数据传回主窗口?
解决办法:原来一直以为是对python的类理解不深刻,然后是Tkinter中的使用就是返回不回去
参照:https://www.jb51.net/article/119817.htm 修改成了类的方式来做。我用的第一种,把值返回给主界面

1)松耦合
说明:
主窗类,继承了 tk.Tk
弹窗类,继承了 tk.Toplevel
要点:
弹窗,将多个数据,打包,放入一个名为 username 的私有 list 对象,销毁弹窗
主窗,待弹窗运行后,通过wait_window方法,取得弹窗的名为 username 私有变量import tkinter as tk
'''松耦合'''
# 弹窗
class MyDialog(tk.Toplevel):def __init__(self):super().__init__()self.title('设置用户信息')# 弹窗界面self.setup_UI()def setup_UI(self):# 第一行(两列)row1 = tk.Frame(self)row1.pack(fill="x")tk.Label(row1, text='姓名:', width=8).pack(side=tk.LEFT)self.name = tk.StringVar()tk.Entry(row1, textvariable=self.name, width=20).pack(side=tk.LEFT)# 第二行row2 = tk.Frame(self)row2.pack(fill="x", ipadx=1, ipady=1)tk.Label(row2, text='年龄:', width=8).pack(side=tk.LEFT)self.age = tk.IntVar()tk.Entry(row2, textvariable=self.age, width=20).pack(side=tk.LEFT)# 第三行row3 = tk.Frame(self)row3.pack(fill="x")tk.Button(row3, text="取消", command=self.cancel).pack(side=tk.RIGHT)tk.Button(row3, text="确定", command=self.ok).pack(side=tk.RIGHT)def ok(self):self.userinfo = [self.name.get(), self.age.get()] # 设置数据self.destroy() # 销毁窗口def cancel(self):self.userinfo = None # 空!self.destroy()
# 主窗
class MyApp(tk.Tk):def __init__(self):super().__init__()#self.pack() # 若继承 tk.Frame ,此句必须有!self.title('用户信息')# 程序参数/数据self.name = '张三'self.age = 30# 程序界面self.setupUI()def setupUI(self):# 第一行(两列)row1 = tk.Frame(self)row1.pack(fill="x")tk.Label(row1, text='姓名:', width=8).pack(side=tk.LEFT)self.l1 = tk.Label(row1, text=self.name, width=20)self.l1.pack(side=tk.LEFT)# 第二行row2 = tk.Frame(self)row2.pack(fill="x")tk.Label(row2, text='年龄:', width=8).pack(side=tk.LEFT)self.l2 = tk.Label(row2, text=self.age, width=20)self.l2.pack(side=tk.LEFT)# 第三行row3 = tk.Frame(self)row3.pack(fill="x")tk.Button(row3, text="设置", command=self.setup_config).pack(side=tk.RIGHT)# 设置参数def setup_config(self):# 接收弹窗的数据res = self.ask_userinfo()#print(res)if res is None: return# 更改参数self.name, self.age = res# 更新界面self.l1.config(text=self.name)self.l2.config(text=self.age)# 弹窗def ask_userinfo(self):inputDialog = MyDialog()self.wait_window(inputDialog) # 这一句很重要!!!return inputDialog.userinfo
if __name__ == '__main__':app = MyApp()app.mainloop()2)紧耦合
说明:
主窗类,继承了 tk.Tk
弹窗类,继承了 tk.Toplevel
要点:
弹窗,显式地保存父窗口,显式地修改父窗口数据,显式地更新父窗口部件,最后销毁弹窗
主窗,待弹窗运行后,通过wait_window方法,返回 Noneimport tkinter as tk
'''紧耦合'''
# 弹窗
class PopupDialog(tk.Toplevel):def __init__(self, parent):super().__init__()self.title('设置用户信息')self.parent = parent # 显式地保留父窗口# 第一行(两列)row1 = tk.Frame(self)row1.pack(fill="x")tk.Label(row1, text='姓名:', width=8).pack(side=tk.LEFT)self.name = tk.StringVar()tk.Entry(row1, textvariable=self.name, width=20).pack(side=tk.LEFT)# 第二行row2 = tk.Frame(self)row2.pack(fill="x", ipadx=1, ipady=1)tk.Label(row2, text='年龄:', width=8).pack(side=tk.LEFT)self.age = tk.IntVar()tk.Entry(row2, textvariable=self.age, width=20).pack(side=tk.LEFT)# 第三行row3 = tk.Frame(self)row3.pack(fill="x")tk.Button(row3, text="取消", command=self.cancel).pack(side=tk.RIGHT)tk.Button(row3, text="确定", command=self.ok).pack(side=tk.RIGHT)def ok(self):# 显式地更改父窗口参数self.parent.name = self.name.get()self.parent.age = self.age.get()# 显式地更新父窗口界面self.parent.l1.config(text=self.parent.name)self.parent.l2.config(text=self.parent.age)self.destroy() # 销毁窗口def cancel(self):self.destroy()
# 主窗
class MyApp(tk.Tk):def __init__(self):super().__init__()# self.pack() # 若继承 tk.Frame,此句必须有!!!self.title('用户信息')# 程序参数self.name = '张三'self.age = 30# 程序界面self.setupUI()def setupUI(self):# 第一行(两列)row1 = tk.Frame(self)row1.pack(fill="x")tk.Label(row1, text='姓名:', width=8).pack(side=tk.LEFT)self.l1 = tk.Label(row1, text=self.name, width=20)self.l1.pack(side=tk.LEFT)# 第二行row2 = tk.Frame(self)row2.pack(fill="x")tk.Label(row2, text='年龄:', width=8).pack(side=tk.LEFT)self.l2 = tk.Label(row2, text=self.age, width=20)self.l2.pack(side=tk.LEFT)# 第三行row3 = tk.Frame(self)row3.pack(fill="x")tk.Button(row3, text="设置", command=self.setup_config).pack(side=tk.RIGHT)# 设置参数def setup_config(self):pw = PopupDialog(self)self.wait_window(pw) # 这一句很重要!!!return
if __name__ == '__main__':app = MyApp()app.mainloop()

问题二、
“Use of super on an old style class” py27环境里面super不支持使用,需要使用老方式来显示
Python类的继承有两种写法,一是老样式(old style),一是新样式(new style),都能解决上述的错误。
解决办法:
参照我的代码。
好的博客:这个涉及到关于py的类和继承,这个有时间再看下,因为直接做项目,蒙头做,回过头再研究吧
https://blog.csdn.net/ws_cs_dn/article/details/37699195
https://blog.csdn.net/yiifaa/article/details/78068970

问题三、
下载验证码到本地,然后使用Tkinter,打开该文件一直打不开。不显示该图片。最开始使用Lab方式来显示图片,反正死活没显示出来,后来使用tk.Canvas 然后显示出来图片……
解释:首先,查了下Tkinter的Lab只支持gif格式的图片显示,如果想支持多格式,需要下PIL包,然后用PIL的TkinterImage来打开图片(参照我代码),最开始我理解的,可能我下载的图片格式不对,我直接把验证码文件下载下来在保存的时候,直接给了后缀,可能文件格式有问题~这是一个
另一个是Lab的用法,可能在类里面的使用方式不对。

另外,我使用 tk.Canvas显示图片,也要格外注意self的使用,不然可能会出现弹窗和主界面主键混乱的情况。。。虽然我实现了功能,很多我也要重新再看下,我只给出解决的方式,至于为什么…………以后慢慢研究吧……

问题四、
在使用chromeDriver时,chromeDriver会有一个弹窗,如何隐藏chromeDriver.exe 黑色弹窗?
修改selenium包文件中
参照:https://stackoverflow.com/questions/33983860/hide-chromedriver-console-in-python
*\selenium\webdriver\common\services.py文件
首先引入 from win32process import CREATE_NO_WINDOW
然后修改start 方法(如下例子),增加creationflags=CREATE_NO_WINDOW

def start(self):"""Starts the Service.:Exceptions:- WebDriverException : Raised either when it can't start the serviceor when it can't connect to the service"""try:cmd = [self.path]cmd.extend(self.command_line_args())self.process = subprocess.Popen(cmd, env=self.env,close_fds=platform.system() != 'Windows',stdout=self.log_file, stderr=self.log_file, creationflags=CREATE_NO_WINDOW)except TypeError:raise

这样子,就不会显示黑色chromeDriver.exe 窗口啦,嘻嘻嘻嘻~

屏蔽,运行自动化脚本
option = webdriver.ChromeOptions()
option.add_argument(‘disable-infobars’)
webdriver.Chrome(chrome_options = option,desired_capabilities = None)

关于打包:
python
打包使用了pyinstaller 来打包。
pip install pyinstaller
pyinstaller -F uc-end.py –noconsole

这篇关于Tkinter和selenium结合实现登录UC后台,最后打包成exe的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089717

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

UE3脚本UnrealScript UC语法点滴

持续更新 目录 类定义修饰符  1.dependson(CLASSNAME) 2.config(ININAME) 3.native 4.notplaceable 5.inherits(CLASSNAME1[,CLASSNAME2,...]) 类对象实例创建 类默认属性设置 变量 1.声明 var local 2.修饰符 config  3.array 类型变量 以及

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Toolbar+DrawerLayout使用详情结合网络各大神

最近也想搞下toolbar+drawerlayout的使用。结合网络上各大神的杰作,我把大部分的内容效果都完成了遍。现在记录下各个功能效果的实现以及一些细节注意点。 这图弹出两个菜单内容都是仿QQ界面的选项。左边一个是drawerlayout的弹窗。右边是toolbar的popup弹窗。 开始实现步骤详情: 1.创建toolbar布局跟drawerlayout布局 <?xml vers

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

移动硬盘盒:便携与交互的完美结合 PD 充电IC

在数字化时代的浪潮中,数据已成为我们生活中不可或缺的一部分。随着数据的不断增长,人们对于数据存储的需求也在不断增加。传统的存储设备如U盘、光盘等,虽然具有一定的便携性,但在容量和稳定性方面往往难以满足现代人的需求。而移动硬盘,以其大容量、高稳定性和可移动性,成为了数据存储的优选方案。然而,单纯的移动硬盘在携带和使用上仍存在诸多不便,于是,移动硬盘盒应运而生,以其独特的便携性和交互性,成为了数据存储

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议