Python 小工具集:浏览器、代理与邮件脚本
整理日常自动化脚本的模块边界、依赖管理和异常处理经验。
项目文稿说明:本文按现有笔记整理,代码是节选或设计示意;仓库实现、线上地址和测试结果尚未逐项核验。后续计划不代表已经完成。
从零打造一个 Python 小工具集:browser_manager、代理网关与自动化脚本
菜牙爱吃菜 · 技术随笔
大家好,我是菜牙。
今天想聊聊我一直在维护的一个小项目——tools。说它小,是因为它没有宏大的架构,也没有几十万行代码,就是一堆"小而实用"的 Python 脚本集合。但正是这个"小工具集",让我踩了不少坑、学到了不少东西,今天拿出来和大家分享一下。
这个项目是干什么的?
一句话总结:把日常重复性的工作自动化掉。
比如:
- 同时开好几个浏览器,每个浏览器走不同的代理(多账号操作)
- 用 GoLogin 管理大量浏览器指纹,自动登录、切换环境
- 通过代理网关统一管理多个代理 IP 的轮换和分配
- 用 IMAP 协议自动处理邮件验证码
- 管理和重置 Cursor AI 的账号配置
这些东西单独看都很琐碎,但组合在一起,就是一套"多账号运营 + 自动化"的基础设施。
模块一览
项目目前包含以下核心模块:
| 模块 | 功能简述 |
|---|---|
browser_manager |
浏览器隔离管理,每个实例绑定独立代理 |
cursor |
Cursor AI 账号管理(注册、重置、配置) |
gateway_standalone |
代理网关,统一管理多个代理出口 |
gologin_auto |
GoLogin 浏览器指纹自动化 |
kookeey |
Kookeey 代理网关集成 |
reset_cursor |
Cursor 账号重置工具 |
test_imap |
IMAP 邮件读取测试脚本;发送通常使用 SMTP |
每个模块都是独立的,可以单独使用,也可以组合起来用。这种"松耦合"的设计让我可以按需扩展,不用动整体架构。
技术栈
项目用到的技术:
- PyQt6:给部分工具做了简单的 GUI 界面,不用每次都敲命令行
- DrissionPage:一个国产的浏览器自动化库,API 设计得很顺手,比 Selenium 简洁不少
- Selenium:老牌浏览器自动化方案,复杂场景还是得靠它
- SQLite:本地轻量存储,保存账号信息、代理配置等
- requests:HTTP 请求,代理网关和 API 调用的基础
## 一个典型的代理网关请求示例
import requests
proxies = {
"http": "http://127.0.0.1:7890",
"https": "http://127.0.0.1:7890",
}
resp = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=10)
print(resp.json())
踩过的坑和学到的东西
1. 浏览器隔离是个大坑
浏览器实例若复用同一用户数据目录,可能共享 Cookie 和 localStorage;普通 WebDriver 新会话不必然串数据。后来改用独立的用户数据目录(--user-data-dir)+ 独立代理的方式,才算真正实现了浏览器隔离。
## browser_manager 中的核心思路
def create_browser(proxy_port: int, user_data_dir: str):
options = Options()
options.add_argument(f"--proxy-server=http://127.0.0.1:{proxy_port}")
options.add_argument(f"--user-data-dir={user_data_dir}")
# 反检测:去掉 webdriver 标记
options.add_argument("--disable-blink-features=AutomationControlled")
return webdriver.Chrome(options=options)
教训:浏览器隔离不是加个代理就完事,用户数据目录才是关键。
2. 代理网关设计要考虑失败重试
代理 IP 是会过期的,尤其是免费代理。一开始我的网关逻辑很简单:请求 → 返回结果。后来频繁遇到超时、403 等问题,加了自动重试 + 代理池轮换之后才稳定下来。
def request_with_retry(url, max_retries=3):
for i in range(max_retries):
proxy = get_next_proxy() # 从代理池取下一个
try:
return requests.get(url, proxies=proxy, timeout=10)
except Exception as e:
mark_proxy_failed(proxy) # 标记失效
if i == max_retries - 1:
raise
教训:写网络相关代码,永远要考虑失败的情况,并做好重试和降级。
3. 环境变量管理别偷懒
项目里有很多 API Key、密码、代理地址这类敏感信息。一开始我图方便直接硬编码在代码里,后来有一次差点把 .env 文件推到 Git 仓库——还好 .gitignore 挡住了。
现在 .env.example 模板 + python-dotenv 已经是标配:
## .env.example
CURSOR_API_KEY=your_api_key_here
GOLOGIN_TOKEN=your_token_here
KOOKEEY_API_KEY=your_api_key_here
PROXY_POOL_URL=http://your-proxy-pool:8080
from dotenv import load_dotenv
load_dotenv()
import os
api_key = os.getenv("CURSOR_API_KEY")
if not api_key:
raise ValueError("缺少 CURSOR_API_KEY,请检查 .env 文件")
教训:敏感信息一定要放环境变量,.env 文件一定要加到 .gitignore。
4. GUI 不用太复杂
用 PyQt6 做界面的时候,我一开始想做个"现代化"的深色主题、多标签页、可拖拽布局……后来发现完全没必要。使用者就是我自己,一个简单的表格 + 几个按钮就够了。
教训:工具类软件的界面,能跑就行,别过度设计。
一些反思
做完这个项目之后,我有几个比较深的感受:
-
小工具也有架构:虽然叫"小工具集",但模块之间的依赖关系、数据流向还是要理清楚。没有架构的小工具,之后维护起来就是灾难。
-
自动化脚本的核心不是代码,是异常处理:正常情况下谁都写得出来,真正体现水平的是各种异常情况的处理——网络超时、代理失效、账号被封、页面改版。
-
写文档很重要:这个项目我断断续续维护了好几个月,中间有好几次隔了快一个月再来看代码,发现自己都忘了某些模块是干什么的。所以现在强制自己写 README 和注释。
-
保持简单:这个项目没有用 Docker、没有用微服务、没有用消息队列——因为不需要。过度工程化比不工程化更可怕。
最后
如果你也在维护类似的小工具集,欢迎交流。这种项目没什么"高大上"的东西,但确实能实实在在地提升效率。
代码不复杂,但每一行都是真实踩坑之后的结晶。
菜牙爱吃菜,一个爱折腾的开发者。欢迎关注,持续分享实用小技巧。