Python WebDriver
最后修改于 2025 年 3 月 6 日
在本文中,我们将展示如何使用 Python 中的 WebDriver 自动化 web 浏览器。WebDriver 是一个远程控制接口,可以对用户代理(即 web 浏览器)进行自省和控制。它提供了一个平台和语言无关的线路协议,供进程外的程序远程指示 web 浏览器的行为。
WebDriver 规范定义了一个类似 REST 的 API,用于与 web 浏览器交互。 此 REST API 使用标准的 HTTP 方法(GET、POST、DELETE)来对浏览器会话、网页上的元素和其他浏览器相关资源执行操作。 每个操作都与特定的 URL 端点相关联,WebDriver 客户端与 WebDriver 服务器通信以执行命令并检索结果。
ChromeDriver 是一个独立的服务器,它实现了 Google Chrome 的 WebDriver 协议。 它充当用 Python、Java 等语言编写的测试脚本和 Chrome 浏览器之间的桥梁。 当您运行自动化测试时,ChromeDriver 会与 Chrome 通信以执行您指定的命令和操作。 它支持各种功能,例如无头模式、移动设备模拟等。
安装 ChromeDriver
在使用 WebDriver 之前,您需要下载 ChromeDriver。 您可以从以下链接下载它
https://googlechromelabs.github.io/chrome-for-testing/#stable
确保 ChromeDriver 的版本与您的 Chrome 浏览器版本匹配。 您可以在此处查看 ChromeDriver 的实施状态
https://chromium.googlesource.com/chromium/src/+/master/docs/chromedriver_status.md
获取 ChromeDriver 状态
以下示例演示了如何使用 REST API 检查 ChromeDriver 的状态。
import requests def get_chrome_driver_status(): url = "https://:9515/status" try: response = requests.get(url) print(response) code = response.status_code if code == 200: print("OK - 200") else: print(f"Failed. HTTP Status Code: {code}") except requests.exceptions.RequestException as e: print(f"An error occurred while connecting to ChromeDriver: {e}") if __name__ == "__main__": get_chrome_driver_status()
在此脚本中,我们使用 requests
库通过向 https://:9515/status
的 /status
端点发送 HTTP GET 请求,直接与 ChromeDriver 的 REST API 交互。 此端点由 ChromeDriver 服务器提供,该服务器必须在本地端口 9515(默认端口)上运行才能使此脚本正常工作——通常,您会在执行此代码之前通过命令行手动启动 ChromeDriver(例如,chromedriver
)。 response
对象包含服务器的回复,我们通过打印它来查看详细信息,例如标头和内容。
然后,我们使用 response.status_code
提取 HTTP 状态代码。状态代码 200 表示 ChromeDriver 正在运行并准备好接受命令,而其他代码(例如,404 或 500)表示服务器未运行或配置错误等问题。 try-except
块捕获潜在错误,例如网络故障或 ChromeDriver 未激活,并打印描述性消息。此示例是一个简单的诊断工具,用于在运行更复杂的自动化任务之前验证 ChromeDriver 的可用性。
获取网页标题
此示例演示了如何使用 WebDriver REST API 检索网页的标题。
import requests def get_webpage_title(url): chromedriver_url = "https://:9515" try: session_response = requests.post(f"{chromedriver_url}/session", json={ "capabilities": { "alwaysMatch": { "browserName": "chrome", "goog:chromeOptions": { "args": ["--headless"] } } } }) session_response.raise_for_status() session_data = session_response.json() session_id = session_data["value"]["sessionId"] print(f"Session created with ID: {session_id}") navigate_response = requests.post( f"{chromedriver_url}/session/{session_id}/url", json={"url": url} ) navigate_response.raise_for_status() print(f"Navigated to: {url}") title_resp = requests.get( f"{chromedriver_url}/session/{session_id}/title", ) title_resp.raise_for_status() title_data = title_resp.json() title = title_data["value"] print(f"The title of the webpage is: {title}") delete_session_response = requests.delete( f"{chromedriver_url}/session/{session_id}") delete_session_response.raise_for_status() print("Session deleted successfully.") except requests.exceptions.RequestException as e: print(f"An error occurred while interacting with ChromeDriver: {e}") if __name__ == "__main__": target_url = "https://example.com/" get_webpage_title(target_url)
此脚本演示了如何使用 ChromeDriver 的 REST API 自动化浏览器会话并检索网页的标题。 它首先向 /session
发送 POST 请求以创建新的浏览器会话,指定 Chrome 作为浏览器并启用无头模式(通过 --headless
)以在没有可见 UI 的情况下运行,这非常适合在服务器或 CI/CD 管道上进行自动化测试。 响应提供了一个 sessionId
,它是此会话的唯一标识符,我们提取该标识符并在后续请求中使用。 接下来,向 /session/{session_id}/url
发送 POST 请求,将浏览器导航到目标 URL(例如,https://example.com/
),模拟用户输入地址。
然后,向 /session/{session_id}/title
发送 GET 请求,获取页面的标题(例如,“Example Domain”),该标题以 JSON 格式返回并从 "value"
键中提取。 最后,向 /session/{session_id}
发送 DELETE 请求以终止会话,确保释放资源。 每个请求都使用 raise_for_status()
来检查 HTTP 错误(例如,404 或 500),并且 try-except
块捕获更广泛的问题,例如网络故障或 ChromeDriver 未运行。 中间打印语句提供有关每个步骤的反馈,使其成为通过 WebDriver 协议进行会话管理和基本页面交互的强大示例。
单击按钮
此示例演示了如何使用 WebDriver 单击网页上的按钮。
import requests def click_button_on_page(url): chromedriver_url = "https://:9515" try: session_response = requests.post(f"{chromedriver_url}/session", json={ "capabilities": { "alwaysMatch": { "browserName": "chrome", "goog:chromeOptions": { "args": ["--headless"] } } } }) session_response.raise_for_status() session_data = session_response.json() session_id = session_data["value"]["sessionId"] print(f"Session created with ID: {session_id}") navigate_response = requests.post( f"{chromedriver_url}/session/{session_id}/url", json={"url": url} ) navigate_response.raise_for_status() print(f"Navigated to: {url}") find_element_response = requests.post( f"{chromedriver_url}/session/{session_id}/element", json={"using": "tag name", "value": "button"} ) find_element_response.raise_for_status() element_data = find_element_response.json() button_element_id = element_data["value"]["element-6066-11e4-a52e-4f735466cecf"] print(f"Button element found with ID: {button_element_id}") click_response = requests.post( f"{chromedriver_url}/session/{session_id}/element/{button_element_id}/click", json={} ) click_response.raise_for_status() print("Button clicked successfully.") delete_session_response = requests.delete( f"{chromedriver_url}/session/{session_id}") delete_session_response.raise_for_status() print("Session deleted successfully.") except requests.exceptions.RequestException as e: print(f"An error occurred while interacting with ChromeDriver: {e}") if __name__ == "__main__": target_url = "https://webcode.me/click.html" click_button_on_page(target_url)
此脚本展示了如何在无头模式下使用 ChromeDriver 的 REST API 在网页上查找和单击按钮。 它首先使用 POST 请求向 /session
创建一个新的 Chrome 会话,指定 --headless
以隐形运行,并检索 sessionId
以供后续命令使用。
然后,浏览器通过向 /url
发送 POST 请求导航到 https://webcode.me/click.html
— 一个带有按钮的简单测试页面。 为了找到该按钮,向 /element
发送 POST 请求,使用“标签名称”定位器策略,其中 "button"
作为值,返回第一个 <button>
元素的唯一 ID(例如,element-6066-11e4-a52e-4f735466cecf
),它遵循 WebDriver 的元素引用格式。 然后,向 /element/{button_element_id}/click
发送 POST 请求,模拟鼠标单击按钮,从而触发任何关联的操作(例如,测试页面上的 JavaScript 事件)。 会话通过向 /session/{session_id}
发送 DELETE 请求来清理。
通过 raise_for_status()
和 try-except
块进行错误处理可确保可靠性,而打印语句可确认每个步骤。 此示例重点介绍元素交互,但在实践中,对于具有多个按钮的复杂页面,可能需要更具体的定位器(例如,ID 或 CSS 选择器)。
截取屏幕截图
此示例显示了如何使用 WebDriver 截取网页的屏幕截图。
import requests import base64 def get_webpage_screenshot(url): chromedriver_url = "https://:9515" try: session_response = requests.post(f"{chromedriver_url}/session", json={ "capabilities": { "alwaysMatch": { "browserName": "chrome", "goog:chromeOptions": { "args": ["--headless"] } } } }) session_response.raise_for_status() session_data = session_response.json() session_id = session_data["value"]["sessionId"] print(f"Session created with ID: {session_id}") navigate_response = requests.post( f"{chromedriver_url}/session/{session_id}/url", json={"url": url} ) navigate_response.raise_for_status() print(f"Navigated to: {url}") screenshot_response = requests.get( f"{chromedriver_url}/session/{session_id}/screenshot" ) screenshot_response.raise_for_status() screenshot_data = screenshot_response.json() screenshot_base64 = screenshot_data["value"] with open("screenshot.png", "wb") as f: f.write(base64.b64decode(screenshot_base64)) print("Screenshot saved as screenshot.png") delete_session_response = requests.delete( f"{chromedriver_url}/session/{session_id}") delete_session_response.raise_for_status() print("Session deleted successfully.") except requests.exceptions.RequestException as e: print(f"An error occurred while interacting with ChromeDriver: {e}") if __name__ == "__main__": target_url = "https://example.com/" get_webpage_screenshot(target_url)
此脚本演示了如何在无头模式下使用 ChromeDriver 的 REST API 捕获网页屏幕截图。 它使用 POST 请求向 /session
启动会话,配置 Chrome 以无头方式运行,并检索 sessionId
。 浏览器通过向 /url
发送 POST 请求导航到 https://example.com/
,从而隐形地加载页面。 然后,向 /screenshot
发送 GET 请求,以捕获可见的视口作为 base64 编码的字符串,该字符串在 JSON 响应的 "value"
键中返回。
该脚本使用 base64.b64decode
解码此字符串,并以二进制模式 ("wb"
) 将其写入名为 screenshot.png
的文件中,从而在工作目录中创建可查看的 PNG 图像。 会话通过向 /session/{session_id}
发送 DELETE 请求来终止。 错误处理确保如果 ChromeDriver 未运行或出现网络问题,脚本会正常失败,而打印语句会跟踪进度。 此功能对于可视化测试、调试或存档网页状态特别有用,但屏幕截图的大小取决于无头浏览器的默认窗口尺寸。
最大化浏览器窗口
此示例演示了如何使用 WebDriver 最大化浏览器窗口。
import requests import time def maximize_browser_window(url): chromedriver_url = "https://:9515" try: session_response = requests.post(f"{chromedriver_url}/session", json={ "capabilities": { "alwaysMatch": { "browserName": "chrome", } } }) session_response.raise_for_status() session_data = session_response.json() session_id = session_data["value"]["sessionId"] print(f"Session created with ID: {session_id}") navigate_response = requests.post( f"{chromedriver_url}/session/{session_id}/url", json={"url": url} ) navigate_response.raise_for_status() print(f"Navigated to: {url}") time.sleep(5) maximize_response = requests.post( f"{chromedriver_url}/session/{session_id}/window/maximize", json={} ) maximize_response.raise_for_status() print("Browser window maximized.") time.sleep(3) delete_session_response = requests.delete( f"{chromedriver_url}/session/{session_id}") delete_session_response.raise_for_status() print("Session deleted successfully.") except requests.exceptions.RequestException as e: print(f"An error occurred while interacting with ChromeDriver: {e}") if __name__ == "__main__": target_url = "https://example.com/" maximize_browser_window(target_url)
此脚本演示了如何使用 WebDriver REST API 最大化 Chrome 浏览器窗口,该窗口在可见模式下运行(没有 --headless
标志)。 它首先向 /session
发送 POST 请求来创建会话,获取 sessionId
,然后使用 POST 向 /url
导航到 https://example.com/
。
time.sleep(5)
暂停,使用户可以在最大化之前观察初始窗口大小 — 这对于演示很有用,但在生产环境中是可选的。 关键操作是向 /window/maximize
发送 POST 请求,该请求会调整浏览器大小以填充屏幕,从而模拟用户单击最大化按钮。
另一个 time.sleep(3)
允许在会话以向 /session/{session_id}
发送 DELETE 请求结束之前观察最大化状态。 通过 raise_for_status()
和 try-except
进行错误处理可确保可靠性,而打印语句可确认每个步骤。 此功能有助于确保测试中一致的视口大小或捕获全页屏幕截图(如果在屏幕截图命令之后),尽管其效果仅在非无头模式下可见。
来源
在本文中,我们探讨了使用 Python 中的 WebDriver 自动化 web 浏览器的基础知识。
作者
列出所有 Python 教程。