最近腾讯云开发者社区的活动越来越多,很多优秀的开发者也经常收到小助理邀请填写中奖收货地址的消息。最近在社区普天同庆的年终活动中,我也是有幸获得了几个可爱周边,所以也遇到了每次都要手敲电话号码、收货信息的问题。
所以在空闲之余,就用 Python + PyQt6 开发了一个腾讯云获奖表单自动填写的桌面工具。这个工具可以帮助用户快速填写重复的表单信息,支持地址信息的保存和管理。
演示效果:
本程序github地址:腾讯云获奖表单自动填写工具
git clone下来之后,运行 form_filler.py 主程序即可。form_template.html是表单填写页面,可以使用这个页面测试。
这是我当前收集到的两个表单,结构如下:
针对于上面的这个表单,我们通过开发者工具查看HTML元素。
可以看到每个input的class属性都是一样的,而name属性都是唯一的字符,所以这里就可以考虑使用name属性来定位元素。为了避免不同的名单中的name是随机的,所以我又找了一个表单去验证。
这个表单多了一个微信的输入框,这个暂且不管,同样查看HTML。
我们可以看到这个表单的name与上面的表单是相同的。目前没有第三个表单进行验证,如果后续name属性变动的话,就要考虑使用input的顺序和一些其他的元素辅助定位。这里先不考虑这么多,就用name定位。
说到自动化工具,我们自然而然就想到了selenium,加上填写表单之前需要使用微信扫码登录,所以使用selenium无疑是最好的选择。
GUI框架使用的是 PyQt6。相比Tkinter更现代的界面,刚开始我使用Tkinter进行的开发,但是遇到了输入框双击无法编辑、按钮点击无响应等问题,最终放弃使用PyQt6。
最后使用pyinstaller工具,将python打包成exe等PC可运行的桌面应用。
程序的模块主要后台逻辑、GUI页面设计、 个人信息管理、程序打包四个部分。
后台逻辑这一块主要是实现打开浏览器自动填写页面的功能,以及其中包含的一些细节。
我们使用selenium来打开一个浏览器,然后完成扫码登录、页面填写的动作。所以我们要确保已安装Chrome浏览器。
from selenium import webdriver
def __init__(self):
try:
self.driver = webdriver.Chrome()
except Exception as e:
raise Exception(f"无法启动Chrome浏览器: {str(e)}"
表单自动填写就是通过selenium来定位表单的元素,然后将定义的数据变量回填到表单中。主要逻辑代码如下:
def fill_form(self, url, form_data):
try:
self.driver.get(url)
wait = WebDriverWait(self.driver, 10)
# 等待并填写昵称
nickname_input = wait.until(
EC.presence_of_element_located((By.NAME, "7lap1mcqwr7"))
)
nickname_input.send_keys(form_data['nickname'])
# 填写其他字段
name_input = self.driver.find_element(By.NAME, "xepe2botxth")
name_input.send_keys(form_data['name'])
phone_input = self.driver.find_element(By.NAME, "tvvoz8pt5tf")
phone_input.send_keys(form_data['phone'])
address_input = self.driver.find_element(By.NAME, "f54spd7ug5q")
address_input.send_keys(form_data['address'])
EC 是 expected_conditions 的缩写,它是 Selenium 中的一个重要模块,用于定义期望的条件,主要用于显式等待(explicit wait)场景,我们在代码中引入EC。
from selenium.webdriver.support import expected_conditions as EC
在代码中,我们使用EC来等待直到找到 name="7lap1mcqwr7" 的元素出现在DOM中,如果在超时时间内找到了元素,返回该元素。如果超时还没找到,意味着当前表单不符合程序内要填写的表单结构,所以抛出异常。
这里的点击事件,包括勾选复选框同意协议,然后点击提交。后来我把提交按钮的代码注释掉了,原因就是我在测试功能的时候,使用了正式的获奖表单链接,导致我的收货地址填的都是错误的测试数据,但是表单填完之后没法修改,最后只能辛苦小助理添加了备注。
勾选复选框的代码如下:
# 勾选协议复选框
checkbox = self.driver.find_element(By.CLASS_NAME, "f-checkbox")
if not checkbox.is_selected():
checkbox.click()
GUI的设计主要使用 PyQt6 完成的,最初使用的 Tkinter,在开发完成之后发现交互性体验感不太好,所以就换成了 PyQt6。
主窗口设计就是一个简单的布局,提供了查看和修改地址的按钮入口,用户在输入获奖的表单URL之后,点击开始填写按钮就会在浏览器打开表单,然后完成自动化填写。
GUI在样式上确实没有H5页面那么丰富,但是我们可以使用一些简单设置。为了让表单在任何尺寸的终端都能保持不变形,这里使用了setFixedSize为窗口设置了固定尺寸。布局方面使用了QVBoxLayout垂直布局,并设置了适当的间距和边距,这样可以让界面元素分布更加合理。
def setup_ui(self):
self.setWindowTitle("腾讯云表单自动填写工具")
self.setFixedSize(500, 300)
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
layout.setSpacing(20)
layout.setContentsMargins(20, 20, 20, 20)
最终窗口样式如下:
其实按钮的设计比较简单,这里是是一共三个按钮。查看地址按钮就是查看维护的个人信息。
通过修改按钮出发弹窗,可以在里面修改个人信息。
在修改个人信息页面中,增加了电话号码格式的验证:
def validate_phone(self, text):
"""验证电话号码格式"""
text = ''.join(filter(str.isdigit, text))
is_valid = len(text) == 11 and text.startswith(('13', '14', '15', '16', '17', '18', '19'))
if text:
if is_valid:
phone_entry.setStyleSheet("border: 1px solid #52c41a;")
else:
phone_entry.setStyleSheet("border: 1px solid #ff4d4f;")
电话号码验证自动过滤非数字字符,提升用户体验,实时验证号码格式,立即提供反馈,以及使用绿色和红色边框直观显示验证结果。
这个桌面工具主要是为了自动填写个人信息,所以需要实现维护个人信息的功能。在一个PC首次使用这个工具的时候,就会弹出提示框强制你修改个人信息。
点击OK之后,就会跳转到个人信息修改页面。
修改之后点击保存即可。在这个功能实现中,我们只需要考虑一个问题:如何判断是首次使用? 首次使用功能主要通过比较当前配置与默认配置来判断,如果完全一致则认为是首次使用。实现包含以下几个关键部分:
在 config.py 中定义默认个人信息配置:
DEFAULT_FORM_DATA = {
'nickname': '测试昵称',
'name': '张三',
'phone': '13800138000',
'address': '广东省深圳市南山区腾讯大厦'
}
这个就是一个模板,在这里可以修改为空,但是不要修改成你的实际收货地址,因为需要用这个文件判断是否首次使用,所以不能和你的实际信息一致。
在 config_manager.py 中实现配置的加载和保存:
def load_config():
# 加载配置文件
try:
with open('form_config.json', 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
return DEFAULT_FORM_DATA.copy()
def save_config(config):
# 保存配置到文件
with open('form_config.json', 'w', encoding='utf-8') as f:
json.dump(config, f, ensure_ascii=False, indent=2)
代码主要实现了form_config.json 的加载,在原始的程序目录中是没有这个文件的,所以load_config的逻辑是默认从DEFAULT_FORM_DATA复制。
在 check_first_run 方法中实现首次使用检测:
def check_first_run(self):
# 检查是否使用默认配置
is_default = all(
self.form_data[key] == DEFAULT_FORM_DATA[key]
for key in DEFAULT_FORM_DATA
)
if is_default:
# 显示强制修改提示
QMessageBox.information(
self,
"首次使用提示",
"首次使用请修改收货地址",
QMessageBox.StandardButton.Ok
)
is_default 是 form_config.json 与 DEFAULT_FORM_DATA 的数据比较结果,如果为True,表示用户未修改个人信息,所以就是用弹出对话框提示用户修改。
但是有的用户真的叛逆(也可能是手滑),在修改之后点击了取消,或者未修改就点击了保存。这就导致用户没把准确的个人信息维护成功,所以在这里增加了修改检测逻辑。
# 强制打开修改对话框,直到用户修改了地址
while is_default:
dialog = FormDataDialog(self, self.form_data, readonly=False)
if dialog.exec():
self.form_data = dialog.result
save_config(self.form_data)
# 检查是否真的修改了
is_default = all(
self.form_data[key] == DEFAULT_FORM_DATA[key]
for key in DEFAULT_FORM_DATA
)
if is_default:
QMessageBox.warning(
self,
"提示",
"请修改默认的收货地址信息!",
QMessageBox.StandardButton.Ok
)
else:
# 用户点击取消,再次提醒
reply = QMessageBox.warning(
self,
"提示",
"首次使用必须修改默认地址,是否继续?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
)
if reply == QMessageBox.StandardButton.No:
sys.exit(0) # 用户选择退出程序
在修改之后点击了取消,或者未修改就点击了保存后关闭修改页面,就会弹出下面提示框:
在修改了个人信息之后,点击保存。
在 form_config.json 中可以看到个人信息已经被修改。
{
"nickname": "叫我阿柒啊",
"name": "阿柒",
"phone": "13800138001",
"address": "广东省深圳市南山区腾讯大厦"
}
在完成了自动化表单填写工具的开发后,为了让没有主机的环境我们需要将其打包成可执行文件,方便用户使用。
在开始打包之前,我们需要确保所有依赖都已正确安装。特别是PyInstaller,它是我们主要的打包工具。这里建议使用venv虚拟环境进行打包。
# 创建虚拟环境
python -m venv venv_build
# 激活虚拟环境
# Windows:
.\venv_build\Scripts\activate
# macOS/Linux:
source venv_build/bin/activate
# 安装依赖
pip install -r requirements.txt
常用的打包命令如下:
# 单文件打包(推荐)
pyinstaller --clean --windowed --onefile --name "表单填写工具" form_filler.py
# 添加图标打包
pyinstaller --clean --windowed --onefile --icon=icon.ico --name "表单填写工具" form_filler.py
在这个程序中,建议去掉onefile参数,这样在打包之后运行的会更快。其中需要关注的参数及其细节:
其实到这里就已经打包完成。
在编译的时候第二个Unix可执行文件已经上传到github,
优化打包大小的策略有:
# 使用UPX压缩
pyinstaller --clean --windowed --onefile --upx-dir=/path/to/upx --name "表单填写工具" form_filler.py
# 排除不需要的模块
pyinstaller --clean --windowed --onefile --exclude-module tkinter --name "表单填写工具" form_filler.py
其实这是第一个很小的工具开发,感觉其实挺简单的,但是在实际开发中也是遇到了很多的问题,不过大部分都已经解决。最后的问题就是pyinstaller打包带来的问题。目前主要是运行打包后的程序时,因为涉及一些解压等操作,程序响应比较慢,这个应该算是通病。
所以我还是建议使用shell的方式调用py文件比较速度,在我的shell目录下创建一个TencentFill.sh文件并编辑。
#!/bin/bash
# 有的macos是.zprofile
source ~/.bash_profile
# 替换成你的项目路径
cd ~/app/cursor/TencentFill
python3.10 form_filler.py
然后给脚本添加执行权限:
chmod +x TencentFill.sh
因为我的shell目录添加在了PATH中,所以我在终端通过直接执行TencentFill.sh就能实现表单自动填写。
本篇文章主要从一个表单的自动填写,讲述了如何使用selenium自动化工具 + 图形化实现一个简单的桌面应用,以此来解放双手,替我们完成重复的工作。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。