本节摘要:点击与输入是交互的骨架,下拉、悬停、拖拽、组合键是血肉,浏览器内脚本执行是最后的后门。本节按"基础交互 → 选择类控件 → 动作链 → 键盘与脚本后门"的顺序把交互 API 地图走全,并划清每种的适用边界与翻车点。定位(3.1)与等待(3.3)解决"找到并等到",本节解决"动得对"——三者凑齐,单条用例的可靠性才算闭环。
先回答一个反问:脚本执行了 click(),就等于模拟了用户点击吗?多数时候是——前面反复说过,Selenium 走的是浏览器原生事件通道,悬停、按下、抬起一应俱全。但"多数时候"三个字值一章的学费:下拉框用点击加选项的方式时灵时不灵;悬停菜单在脚本里一闪而过;拖拽滑块怎么都拖不到位。这些翻车的共同点是:目标控件不是裸的原生控件,而是被前端框架重新实现的复合控件——交互代码必须理解控件的实现方式,而不是只记住一个方法名。
本节的任务就是给你一张交互 API 地图,并标注每块地形的陷阱。先立总览,再逐块展开:

click()、send_keys()、clear() 覆盖日常八成的交互。它们都很简单,翻车点全在"前置条件":点击前元素要可见且可交互,输入前元素要可编辑。前面 3.3 的结论在这里落地——点击配"可点击"条件,输入配"可见"条件,别拿裸定位直接交互。
输入类还有一个高频细节:send_keys 是追加而非覆盖,输入框已有默认值时,结果是新旧拼接。正确姿势是先清后填,而 clear() 在某些前端框架里不触发框架监听的输入事件,导致表单校验状态没更新——遇到这种页面,用全选加删除的键盘组合替代清空:
from selenium.webdriver.common.keys import Keys box = wait.until(EC.element_to_be_clickable((By.ID, "phone"))) box.send_keys(Keys.CONTROL, "a") # 全选 box.send_keys(Keys.DELETE) # 删除选中内容 box.send_keys("13800001111")
原生下拉(select 标签)有专属工具类,提供按值、按索引、按可见文本三种选法:
from selenium.webdriver.support.ui import Select select = Select(driver.find_element(By.ID, "province")) select.select_by_value("zhejiang") # 按option的value属性 select.select_by_visible_text("浙江省") # 按用户看到的文字 print(len(select.options), "个选项")
必须泼一盆冷水:Select 只认原生 select 标签。现代前端组件库的下拉几乎都是"输入框加浮层"的自绘控件——点击展开、点击选项、可能还有搜索过滤。对自绘控件,Select 类直接报错,正确做法回归动作链:等浮层出现,点击目标选项。判断依据就看一眼 DOM:是 select 标签用 Select,是自绘浮层用点击。
鼠标悬停、右键、双击、按住拖动,这组操作由动作链承担。它把一串动作攒成一个序列,一次派发给浏览器:
from selenium.webdriver import ActionChains menu = driver.find_element(By.CSS_SELECTOR, "[data-testid='user-menu']") item = driver.find_element(By.CSS_SELECTOR, "[data-testid='logout-item']") ActionChains(driver).move_to_element(menu).pause(0.3).click(item).perform()
这个例子里藏着动作链最重要的心法:悬停展开的菜单是"鼠标移开后自动收起"的,悬停与点击之间那零点几秒的停顿,是给菜单的展开动画留时间。没有停顿的连招,菜单还没展开、点击已经落空。拖拽同理,按下、移动、释放三步在序列里一气呵成,滑块类验证控件的自动化几乎全靠它。
键盘的高级用法围绕修饰键展开:按住 Shift 连续输入得到大写、组合键触发快捷操作、方向键在自绘下拉里逐项移动。它们都是 send_keys 的参数变体,配合动作链的 key_down、key_up 还能表达"按住不放"的过程性操作。富文本编辑器是键盘进阶的主战场——这类控件内部是可编辑区域而非输入框,点击定位光标后全靠键盘序列组织内容。
最后是后门:执行任意浏览器端脚本。它最大的价值是滚动——把元素滚进可视区再交互,或者直接滚到页面底部触发懒加载:
target = driver.find_element(By.CSS_SELECTOR, "[data-testid='footer']") driver.execute_script("arguments[0].scrollIntoView({block:'center'});", target) driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
之所以叫后门,是因为它绕过了真实用户路径:脚本直接改属性、直接触发事件,浏览器无法区分这是脚本还是用户。后门能救急——遮挡点不到、悬停被动画吞掉时,它是逃生通道;但常走后门会让用例失去"模拟真实用户"的证明力,点击被脚本绕过的按钮,测不出真实点击路径上的问题。纪律就一句话:正门优先,动作链次之,后门逃生。
问:怎么快速判断一个控件是原生还是自绘? 看一眼 DOM:点开控件后出现的浮层如果是 select 标签的原生展开,开发者工具里不会有新元素;自绘控件的浮层是一组新渲染的页面元素(通常是列表加定位属性)。两秒的观察决定用 Select 类还是用等待加点击。
问:动作链的停顿设多少合适? 以"展开动画播完"为准,常见组件的动画在一百到四百毫秒之间,零点三秒是稳妥起点。更稳的写法是停顿加条件:停顿后等浮层里的目标项可点击,动画慢时条件兜底,动画快时不白等。
问:脚本后门执行脚本会不会带来安全风险? 脚本运行在与用例相同的浏览器上下文里,能做的行为与页面自身脚本相同,不构成额外攻击面;真正的风险是工程性的——后门写法绕过真实路径,掩盖交互问题。把后门调用集中在工具函数并加注释说明"为何必须走后门",评审时一目了然。
定位、等待、交互三关全通,你已经能写出可靠的单条用例。下一章解决规模问题:几十条、几百条用例怎么组织成改不散、看得懂、跑得快的工程。