在百度自动输入关键词:如何使用 Selenium 定位和操作网页元素
在使用 Selenium 自动化测试或数据采集时,一个常见任务就是模拟人在浏览器中输入关键词进行搜索。比如,我们希望在百度搜索框中输入 “白月黑羽” 并执行搜索。这类操作本质上是“控制网页中的界面元素”。
操作网页元素的前提:先“定位”它们
Selenium 控制网页的第一步,是定位我们要操作的元素。也就是说,在输入、点击之前,必须让程序知道我们想控制的是哪一个元素。这就像让一个机器人去按按钮之前,得先告诉它按钮在哪里。
元素定位的原理
定位元素的本质,是通过元素的某些“特征”来让浏览器识别出你想操作的对象。常用的特征包括:
id
class
tag
标签名css选择器
等
如何查看网页元素的特征?
我们可以使用 浏览器的开发者工具(F12) 来查看网页的 HTML 结构。在 Chrome 浏览器中:
- 打开网页,按下
F12
。 - 点击 “Elements” 标签页。
- 使用左上角的选取工具(鼠标图标),在页面中点选你想查看的区域。
这时,页面中某个控件的 HTML 标签会高亮显示,我们就可以看到它的 id
、class
等属性。
使用 id
属性来定位元素
如果某个 HTML 元素定义了 id
属性,那么我们就可以用它来快速、准确地定位这个元素。因为在一个 HTML 页面中,id
是唯一的,使用 id
定位是最简单高效的方式。
示例代码:在网页中输入关键词“通讯”
from selenium import webdriver
from selenium.webdriver.common.by import By
wd = webdriver.Chrome()
wd.get('https://www.byhy.net/cdn2/files/selenium/stock1.html')
element = wd.find_element(By.ID, 'kw') # 定位输入框
element.send_keys('通讯\n') # 输入“通讯”并模拟回车
解释:
wd.find_element(By.ID, 'kw')
:通过id="kw"
找到输入框。send_keys('通讯\n')
:像人在键盘上打字一样输入文字,并敲击回车键。
Selenium 4 的定位语法注意事项
从 Selenium 4 开始,之前的一些写法已被废弃。例如:
# 旧写法(已过时)
wd.find_element_by_id('username')
推荐使用统一的 By
方式:
from selenium.webdriver.common.by import By
# 新写法
wd.find_element(By.ID, 'username')
使用 class
或 tag
选择多个元素
有些元素没有 id
,但有 class
,这种情况下,我们可以用类名来定位:
elements = wd.find_elements(By.CLASS_NAME, 'animal') # 获取多个元素
这里用的是 find_elements
(注意复数),返回的是一个元素列表。例如,如果页面上有多个 <div class="animal">
,这行代码就会获取全部这些元素。
可以通过 .text
属性获取元素的文字内容:
for e in elements:
print(e.text)
类似地,还可以用标签名选择元素:
elements = wd.find_elements(By.TAG_NAME, 'div')
find_element
vs find_elements
的区别
方法 |
返回值类型 |
找不到元素时的表现 |
|
单个元素 |
抛出 |
|
元素列表 |
返回空列表,不会报错 |
嵌套定位:从某个元素内再查找子元素
Selenium 支持在一个已找到的元素内部继续查找其子元素。
outer = wd.find_element(By.ID, 'container')
inner_spans = outer.find_elements(By.TAG_NAME, 'span')
这表示:先找到 id="container"
的元素,然后从它里面找所有 <span>
标签。
元素可能“暂时”不存在?解决方案是等待
有些网页加载内容需要时间,比如搜索结果。此时立即查找元素会失败。常见错误是:
selenium.common.exceptions.NoSuchElementException
一种解决方案是使用 time.sleep()
暂停几秒等待页面加载:
from time import sleep
sleep(1)
但这种方法效率低,Selenium 提供了更智能的等待机制。
使用 implicitly_wait
实现“智能等待”
wd.implicitly_wait(10) # 最长等待10秒,直到元素出现
这会让 Selenium 在查找元素时,如果没找到,不会立刻报错,而是每隔 0.5 秒重新尝试一次,最多尝试到 10 秒。
完整例子:
wd = webdriver.Chrome()
wd.implicitly_wait(10)
wd.get('https://www.byhy.net/cdn2/files/selenium/stock1.html')
wd.find_element(By.ID, 'kw').send_keys('通讯\n')
result = wd.find_element(By.ID, '1')
print(result.text)
补充说明:什么时候还是需要 sleep
?
虽然 implicitly_wait
解决了大多数等待问题,但并不是万能的。
- 如果页面元素已经存在,但其内容还没更新,那么
implicitly_wait
也无能为力。 - 例如等待动画完成、弹窗完全渲染,有时候仍需用
sleep()
或显式等待(WebDriverWait
)配合使用。