Python网页自动化实战:DrissionPage表单填报与批量数据处理工程化指南
声明:本文技术方案仅供学习研究使用,请遵守目标网站的服务条款。
一、为什么放弃Selenium?
去年接了个需求:每天帮运营往后台系统录几百条数据。第一反应是用Selenium,结果Chrome自动升级后chromedriver版本对不上,生产环境挂了两次。查日志、下驱动、配路径,一套下来半小时没了。
后来同事推荐了DrissionPage 4.x,试了一周,几个痛点确实解决了:
-
驱动问题:不需要手动管chromedriver,开箱自动匹配版本
-
定位写法:支持
text=提交这种按文本定位,比XPath直观,页面结构微调时不容易失效 -
等待逻辑:内置智能等待,不用写一堆
WebDriverWait -
双模式:复杂页面用浏览器模式,简单接口切requests模式直接抓数据
安装就一行:
pip install DrissionPage
注意:4.x版本底层完全自研,不依赖Selenium,跨iframe查找也不需要手动切换,后面会讲到。
二、实战:B端后台表单自动填报
最常见的流程:打开后台 → 登录 → 进表单页 → 填字段 → 提交 → 保存结果。这个流程里几乎涵盖了所有表单交互类型。
我封装了一个FormAutoFiller类,设计原则是每个方法只干一件事,返回布尔值,外层好做流程控制。fill_text_input里的simulate_human参数会在输入时加随机延迟,模拟真实打字节奏,有些后台有风控,这个能规避一部分。
from DrissionPage import Chromium
import time, random
from pathlib import Path
class FormAutoFiller:
def __init__(self):
self.browser = Chromium()
self.tab = self.browser.latest_tab
self.tab.set.timeouts(base=10)
def fill_text_input(self, selector, value, simulate_human=True):
try:
ele = self.tab.ele(selector)
ele.clear()
if simulate_human:
for char in str(value):
ele.input(char)
time.sleep(random.uniform(0.05, 0.15))
else:
ele.input(str(value))
return True
except Exception as e:
print(f"填写失败 {selector}: {e}")
return False
def select_dropdown(self, selector, option_text):
try:
self.tab.ele(selector).click()
time.sleep(0.5)
self.tab.ele(f'text={option_text}').click()
return True
except Exception as e:
print(f"下拉选择失败 {selector}: {e}")
return False
def select_radio(self, selector):
try:
self.tab.ele(selector).click()
return True
except Exception as e:
print(f"单选失败 {selector}: {e}")
return False
def select_checkbox(self, selector, checked=True):
try:
checkbox = self.tab.ele(selector)
if checked != checkbox.prop('checked'):
checkbox.click()
return True
except Exception as e:
print(f"复选框失败 {selector}: {e}")
return False
def fill_textarea(self, selector, value):
try:
ele = self.tab.ele(selector)
ele.clear()
ele.input(value)
return True
except Exception as e:
print(f"文本域失败 {selector}: {e}")
return False
def upload_file(self, selector, file_path):
if not Path(file_path).exists():
print(f"文件不存在: {file_path}")
return False
try:
self.tab.ele(selector).input(file_path)
return True
except Exception as e:
print(f"上传失败 {selector}: {e}")
return False
def click_button(self, selector, human_like=True):
try:
btn = self.tab.ele(selector)
if human_like:
btn.click.at(offset_x=random.randint(-3, 3),
offset_y=random.randint(-3, 3))
else:
btn.click()
return True
except Exception as e:
print(f"点击失败 {selector}: {e}")
return False
def take_screenshot(self, filename):
try:
self.tab.get_screenshot(path=filename, full_page=True)
return True
except Exception as e:
print(f"截图失败: {e}")
return False
def close(self):
self.browser.quit()
使用流程:创建实例 → 打开页面 → 依次调用填写方法 → 提交 → 截图留痕 → 关闭。每个方法都加了异常捕获,外层可以根据返回值决定是否继续执行。
三、元素定位:哪种写法最稳?
DrissionPage的ele()支持多种选择器,以下是我项目里验证过的高稳定性写法:
| 方式 | 示例 | 适用场景 |
|---|---|---|
| CSS选择器 | tab.ele('#username') |
有固定id,性能最好 |
| 文本定位 | tab.ele('text=提交') |
按钮、链接,抗结构变化 |
| 属性定位 | tab.ele('@name=username') |
没有id但有稳定属性 |
| 组合定位 | form.ele('input[type="text"]') |
先定位父元素再缩小范围 |
一个踩坑经验:React/Vue项目里class名经常是动态的(比如css-1a2b3c),但name、placeholder这些业务属性通常不会变。所以优先用text=和@属性名=,比XPath维护成本低。
批量处理时可以用tab.eles('.list-item')返回列表,配合循环处理。
四、动态加载与iframe:4.x版本省了不少事
4.1 等待元素
AJAX动态加载的页面,DrissionPage内置了智能等待,但复杂场景还是要手动兜底:
# 等待元素出现
tab.wait.ele_displayed('#target', timeout=10)
# 等待元素可点击
tab.wait.ele_loaded('#btn', timeout=10)
4.2 iframe处理(4.x改进很大)
以前用Selenium处理嵌套iframe,切来切去代码很啰嗦。DrissionPage 4.x支持跨iframe直接查找:
# 直接定位iframe内的元素,不需要手动switch
tab.ele('t:iframe')
这个在处理多层嵌套的后台系统时很实用,省了不少代码。
五、批量数据驱动:Excel自动填报
实际数据往往来自Excel,配合pandas实现批量处理:
import pandas as pd
from DrissionPage import Chromium
def batch_fill_from_excel(excel_path, url):
df = pd.read_excel(excel_path)
browser = Chromium()
tab = browser.latest_tab
tab.get(url)
for index, row in df.iterrows():
tab.ele('#name').input(row['姓名'])
# 注意:手机号在Excel里可能是数字类型,必须转字符串
tab.ele('#phone').input(str(row['手机号']))
tab.ele('#email').input(row['邮箱'])
tab.ele('#submit').click()
# 等待提交成功提示
tab.wait.ele_displayed('#success-msg', timeout=5)
tab.ele('#add-new').click()
time.sleep(1)
browser.quit()
重点提醒:str(row['手机号'])这个转换不要漏。Excel里手机号默认是数字,直接input()会报错,这个坑我踩过两次。
六、工程化:从脚本到交付
6.1 打包成可执行文件
脚本自己跑没问题,但交给运营同事用,必须打包成EXE。对比过几个方案:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| PyInstaller | 简单直接,文档多 | 体积大(50-200MB),部分杀毒软件误报 | 快速交付、内部使用 |
| Nuitka | 编译成C,运行快 | 配置稍复杂,部分库兼容性需测试 | 性能敏感场景 |
| cx_Freeze | 跨平台支持好 | 社区相对小,资料少 | 需要Win/Mac双平台 |
PyInstaller命令:
pip install pyinstaller
pyinstaller --onefile --windowed form_autofiller.py
体积大是因为打包了Python解释器和依赖库,这是trade-off,没办法。
6.2 加个GUI界面
用tkinter做个简单面板,核心思路:StringVar绑定输入框,"浏览"按钮弹文件选择,"开始"按钮开后台线程跑自动化(避免界面卡死),日志区用scrolledtext实现。
布局分四块:文件选择、网址输入、运行按钮、日志显示。代码量约80行,够用就行,内部工具不要过度设计。
七、常见问题排查
7.1 元素定位不到?
-
在iframe里?→ 4.x支持直接跨iframe查找:
tab.ele('t:iframe') -
还没加载出来?→ 加显式等待:
tab.wait.ele_displayed('#target', timeout=10) -
选择器错了?→ 用开发者工具检查,或用
tab.ele()返回值是否为None判断
7.2 被风控拦截?
-
设置User-Agent模拟真实浏览器:
co.set_user_agent('Mozilla/5.0...') -
设置代理分散来源:
co.set_proxy('http://代理地址:端口') -
降低操作频率,前面
fill_text_input的simulate_human参数就是干这个的
7.3 文件上传失败?
新手常见错误:点击上传按钮,结果弹出了系统文件对话框,自动化控制不了操作系统层面的UI。
正确做法:直接给<input type="file">元素传路径:
tab.ele('input[type="file"]').input('/path/to/file.pdf')
错误做法:
tab.ele('#upload-btn').click() # 不要这样做
八、工程化延伸:脚本多了怎么管?
写多了自动化脚本,几个现实问题会冒出来:
脚本分散:今天写填报,明天写采集,过段时间自己都找不到。建议按业务场景建仓库,统一管。
给同事用门槛高:不是每个人都懂Python。tkinter做GUI + PyInstaller打包成EXE是必要的交付方式。
网页改版维护难:选择器失效要一个个改。建议把选择器集中放到config文件里,不要硬编码,改版时改一处就行。
数据安全:脚本里别硬编码账号密码。敏感配置放环境变量或加密配置文件,别直接提交到Git。
对于需要团队协作、权限控制,或者希望把Python脚本快速封装成带界面工具的场景,市面上有一些RPA工程化方案可以调研。像蓝印RPA这类支持Python直接接入的平台,能把脚本打包成带界面的可执行文件,还能设置授权验证,适合中小企业内部工具的分发管理。如果涉及自动化流程结合AI能力(如自动识别图片内容、智能填写表单),也可以关注下支持大模型API对接的方案,目前主流模型如文心一言、豆包、DeepSeek、Kimi等都已比较成熟,可以按需接入。
九、RPA工具选型建议
| 场景 | 建议方案 | 考虑因素 |
|---|---|---|
| 个人/小团队 | DrissionPage + Python脚本 | 灵活、无额外成本 |
| 中型团队 | 内部脚本仓库 + 版本控制 | 需考虑交接和维护 |
| 企业级 | 支持Python接入的RPA平台 | 权限、审计、跨部门协作 |
选型没有绝对好坏,匹配团队规模和需求就行。企业级场景如果涉及跨部门协作和审计要求,可以评估蓝印RPA这类支持Python脚本直接接入的方案,既能保留代码灵活性,又能获得企业级的管理和分发能力。
本文基于实际项目经验,整理了DrissionPage 4.x的网页表单自动填报方案:
-
驱动管理:开箱即用,告别chromedriver版本对不上的噩梦
-
元素定位:优先
text=和@属性名=,比XPath维护成本低 -
等待机制:内置智能等待,复杂场景手动兜底
-
iframe处理:4.x跨iframe直接查找,不需要手动切换
-
批量数据:pandas读Excel,注意手机号等数字字段转字符串
-
工程化交付:tkinter做GUI + PyInstaller打包,敏感配置不放代码里
如果实际使用中遇到问题,或者有其他自动化场景想交流,欢迎评论区讨论。
更多推荐
所有评论(0)