Python Playwright自动化浏览网页的基础入门指南

Mia
Mia
发布时间:2026-11-06| 10人浏览过
原创

详解使用Python与Playwright实现网页自动化浏览的完整入门流程,涵盖双步环境安装、BrowserContext隔离机制、语义化元素定位、动态内容提取及常见问题排查。

使用 requests 请求动态网页时,返回的 HTML 往往只有一个空的容器节点,真正的数据需要浏览器执行 JavaScript 脚本后才会渲染出来。Playwright 是由微软开源的现代浏览器自动化工具,它通过底层协议直接控制 Chromium、Firefox 或 WebKit 内核,无需手动下载和匹配驱动版本,并在点击、输入等操作前内置了元素状态自动等待。本文将从环境安装、核心对象结构、页面定位交互、动态数据提取到脚本录制与排错,完整演示如何用 Python 编写可靠的网页自动化脚本。

一、环境准备与两步安装流程

Playwright 的安装分为两个独立步骤:第一步安装 Python 语言绑定库,第二步下载供自动化调用的独立浏览器二进制文件。许多初学者在执行完 pip install 后直接运行代码报错,原因就是遗漏了浏览器内核的下载。

在开始前,请确认本地已安装 Python 3.8 或更高版本。打开终端(Windows 使用 PowerShell 或 CMD,macOS/Linux 使用 Terminal),在项目工作目录下创建并激活虚拟环境,然后依次执行以下两条命令:

# 1. 安装 Playwright 的 Python 库
pip install playwright

# 2. 下载 Chromium 浏览器内核(推荐入门只装 chromium 以节省磁盘空间)
playwright install chromium
示例输出(终端执行 playwright install chromium 的返回片段)Downloading Chromium 130.0.6723.31 (playwright build v1140) from https://playwright.azureedge.net/... 158.4 MiB [====================] 100% 0.0s Chromium 130.0.6723.31 (playwright build v1140) downloaded to /Users/username/Library/Caches/ms-playwright/chromium-1140

如果不指定 chromium 而直接运行 playwright install,工具会同时下载 Chromium、Firefox 和 WebKit 三种浏览器内核,占用约 1GB 磁盘空间。日常网页自动化任务使用 Chromium 即可满足需求。若在 Linux 服务器(如 Ubuntu)无界面环境下运行,还需执行 playwright install-deps chromium 补齐系统级图形依赖库。

Python Playwright自动化浏览网页的基础入门指南
图 1:Playwright 的 Python 库与浏览器内核采用分离安装机制,必须依次完成两步配置

二、核心对象结构与第一个自动化脚本

编写代码前,需要先区分 Playwright 内部的三层核心对象:Browser(浏览器实例)、BrowserContext(浏览器上下文)和 Page(标签页)。这三者的关系直接决定了脚本的资源占用和会话隔离方式。

  • Browser(浏览器实例):对应操作系统中启动的一个 Chromium 进程,启动和销毁的开销较大。
  • BrowserContext(浏览器上下文):相当于浏览器中的“无痕窗口”。同一个 Browser 下可以极低成本地创建多个 BrowserContext,它们之间的 Cookie、LocalStorage 和缓存完全隔离,非常适合多账号并发或测试不同登录状态。
  • Page(页面/标签页):隶属于某个上下文的具体网页窗口,所有的网址跳转、点击和文本读取都在 Page 对象上完成。
Python Playwright自动化浏览网页的基础入门指南
图 2:单个 Browser 进程可创建多个相互隔离的 BrowserContext,每个 Context 管理各自的 Page 标签页

Playwright 同时提供同步(sync_api)和异步(async_api)两种编程接口。对于顺序执行的日常自动化任务,推荐使用同步接口配合 Python 的 with 上下文管理器,这样在代码块执行完毕或发生异常时,浏览器进程会自动关闭,不会在系统后台残留僵尸进程。

在工作目录下新建 first_run.py,写入以下完整代码:

from playwright.sync_api import sync_playwright

def run_basic_navigation():
    # 使用 with 管理生命周期,退出缩进块时自动释放资源
    with sync_playwright() as p:
        # headless=False 表示显示可视化的浏览器窗口;默认值为 True(后台无界面运行)
        # slow_mo=500 表示每步操作放慢 500 毫秒,方便肉眼观察执行过程
        browser = p.chromium.launch(headless=False, slow_mo=500)
        
        # 创建独立的浏览器上下文,可在此统一设置窗口分辨率或 User-Agent
        context = browser.new_context(viewport={"width": 1280, "height": 720})
        
        # 在当前上下文中打开一个新标签页
        page = context.new_page()
        
        # 访问目标网址
        page.goto("https://example.com")
        
        # 打印页面标题与当前 URL
        print("网页标题:", page.title())
        print("当前网址:", page.url)
        
        # 显式关闭浏览器
        browser.close()

if __name__ == "__main__":
    run_basic_navigation()

在终端运行 python first_run.py,屏幕上会弹出一个 Chromium 窗口并加载目标页面,随后自动关闭,终端输出如下:

示例输出(运行 python first_run.py)网页标题: Example Domain 当前网址: https://example.com/
关于调试与正式运行的切换:编写和调试脚本阶段,建议保留 headless=False 和 slow_mo=500,以便直观看到页面停留在哪一步;当脚本调试稳定、准备放入定时任务或服务器后台执行时,去掉 slow_mo 并将 headless 设为 True,执行速度会显著提升。

三、页面元素定位与表单交互

打开网页后,最核心的操作是找到目标输入框或按钮并执行交互。与早期工具直接查找节点并立即点击不同,Playwright 引入了 Locator(定位器)和自动等待机制(Auto-waiting)。创建 Locator 时并不会立刻去页面抓取元素,只有在实际调用 .click() 或 .fill() 时,Playwright 才会去定位元素,并自动等待该元素满足“已挂载到 DOM、可见、位置稳定(动画结束)、未被遮挡且处于可用状态”后才真正触发动作。

Python Playwright自动化浏览网页的基础入门指南
图 3:Locator 在执行交互前的自动等待机制,避免了硬编码 sleep 带来的等待不足或时间浪费

常用定位方式与选择依据

网页改版时,元素的 CSS 类名(如 .btn-primary-v2)或层级结构经常变化,但面向用户的文字和角色属性相对稳定。因此,定位元素时建议优先采用面向用户语义的方法,其次再使用 CSS 选择器:

定位方法 适用场景 代码示例
page.get_by_role() 定位按钮、链接、标题、复选框等具有明确交互角色的元素 page.get_by_role("button", name="提交")
page.get_by_placeholder() 定位带有占位提示词(placeholder 属性)的输入框 page.get_by_placeholder("请输入搜索关键词")
page.get_by_label() 定位关联了 <label> 标签的表单输入框 page.get_by_label("邮箱地址")
page.get_by_text() 按页面显示的可见文本定位非表单元素 page.get_by_text("更多详情", exact=True)
page.locator() 元素缺乏文本特征时,使用标准 CSS 选择器或 ID 定位 page.locator("#search-input")

表单填写与按键交互示例

下面的代码演示如何打开 Wikipedia 首页,在搜索框中输入关键词,并按下回车键跳转到目标词条页面。将其保存为 form_interact.py:

from playwright.sync_api import sync_playwright

def search_keyword():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False, slow_mo=300)
        page = browser.new_page()
        
        # 1. 访问目标站点
        page.goto("https://www.wikipedia.org/")
        
        # 2. 通过 CSS ID 定位搜索输入框,并用 fill() 清空原内容后填入新文本
        search_box = page.locator("#searchInput")
        search_box.fill("Playwright")
        
        # 3. 模拟在输入框上按下键盘 Enter 键提交表单(也可定位搜索按钮后调用 .click())
        search_box.press("Enter")
        
        # 4. 等待新页面的主标题元素加载并打印标题文本
        heading = page.locator("#firstHeading")
        print("跳转后词条主标题:", heading.inner_text())
        
        browser.close()

if __name__ == "__main__":
    search_keyword()

这里需要注意 fill() 与逐字输入的区别:fill("Playwright") 会先清空输入框中的已有文字,再一次性填入目标字符串,速度极快且适合绝大多数表单;如果目标网站依赖键盘敲击事件触发实时下拉联想列表,则应改用 search_box.press_sequentially("Playwright", delay=100) 来模拟间隔 100 毫秒的逐字敲击。

四、提取动态渲染数据与页面截图

当页面通过异步请求(AJAX/Fetch)加载完列表数据后,我们需要将网页上的文字、链接提取到 Python 变量中,或保存网页截图留存证据。在 Playwright 中,提取列表数据最稳妥的做法是先等待列表容器渲染完成,再通过 locator.all() 遍历每个条目。

以下示例访问公开的网页抓取练习站点 https://quotes.toscrape.com/js/(该页面的名言列表完全由 JavaScript 动态生成,普通 HTTP 请求无法直接获取),提取前 5 条名言的正文与作者,并对页面进行截图。新建 extract_data.py:

from playwright.sync_api import sync_playwright

def extract_dynamic_quotes():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        
        # 1. 打开完全由 JavaScript 渲染的页面
        page.goto("https://quotes.toscrape.com/js/")
        
        # 2. 显式等待至少一个 .quote 元素出现在页面上,确保 JS 已执行完毕
        page.wait_for_selector(".quote", state="visible", timeout=10000)
        
        # 3. 获取所有匹配的 .quote 元素定位器列表
        quote_cards = page.locator(".quote").all()
        print(f"当前页面共渲染出 {len(quote_cards)} 条内容,提取前 3 条:\n")
        
        # 4. 在每个卡片内部做相对定位(链式调用 locator),分别提取正文和作者
        for index, card in enumerate(quote_cards[:3], start=1):
            text = card.locator(".text").inner_text()
            author = card.locator(".author").inner_text()
            print(f"[{index}] 作者: {author}")
            print(f"    内容: {text}\n")
            
        # 5. 保存整个网页的长截图到当前目录(full_page=True 会截取滚动条外的完整高度)
        page.screenshot(path="quotes_page.png", full_page=True)
        print("长截图已保存至当前目录: quotes_page.png")
        
        browser.close()

if __name__ == "__main__":
    extract_dynamic_quotes()
示例输出(运行 python extract_data.py)当前页面共渲染出 10 条内容,提取前 3 条: [1] 作者: Albert Einstein 内容: “The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.” [2] 作者: J.K. Rowling 内容: “It is our choices, Harry, that show what we truly are, far more than our abilities.” [3] 作者: Albert Einstein 内容: “There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.” 长截图已保存至当前目录: quotes_page.png

在提取数据时,有三个细节容易导致结果异常:

  1. 必须在调用 .all() 之前等待元素出现:locator.all() 不会像 click() 那样自动等待元素加载,它会立即返回当前时刻页面上已存在的匹配元素列表。如果页面刚打开、JS 尚未执行完就调用 .all(),会直接得到空列表 []。因此前面必须加上 page.wait_for_selector(".quote") 或 page.locator(".quote").first.wait_for()。
  2. 区分 inner_text() 与 text_content():inner_text() 只返回页面上用户肉眼可见的文本,并会自动忽略隐藏元素;而 text_content() 会把节点内包含 display: none 在内的所有原始文本及多余换行一并取出。常规提取推荐使用 inner_text()。
  3. 读取链接地址或图片路径:如果要提取 <a href="..."> 中的网址或 <img src="..."> 的地址,不能用 inner_text(),应调用 card.locator("a").get_attribute("href")。

五、使用 Codegen 自动录制脚本与常见问题排查

1. 用 playwright codegen 自动生成定位代码

面对结构复杂的网页,手动打开浏览器开发者工具(F12)逐个查找元素特征非常耗时。Playwright 内置了可视化录制工具 codegen,可以直接记录你在浏览器中的点击、输入动作,并实时转换成带语义定位器的 Python 代码。

在终端直接执行以下命令(将末尾网址替换为你要操作的目标网站):

playwright codegen https://quotes.toscrape.com/login

执行后会同时弹出两个窗口:左侧是受控的 Chromium 浏览器,右侧是 Playwright Inspector 代码面板。当鼠标在左侧网页上悬停时,元素下方会实时浮现推荐的定位器(如 get_by_role("textbox"));你在网页上输入账号、点击登录按钮后,右侧面板会自动生成完整的 Python 脚本,点击右上角的复制按钮即可粘贴到项目文件中修改使用。

2. 常见报错与解决方式

在初次编写自动化脚本时,最常遇到以下三类问题:

  • 报错 Strict mode violation: locator("...") resolved to N elements(严格模式冲突)
    原因:Playwright 默认启用严格模式。当你对某个定位器调用 .click() 或 .inner_text() 时,如果该选择器在页面上匹配到了 2 个或更多元素,Playwright 会拒绝猜测你想操作哪一个并直接报错。
    解决方法:补充更精确的过滤条件,或者明确指定索引,例如使用 locator(".btn").first.click() 点击第一个,或用 locator(".btn").nth(1).click() 点击第二个(索引从 0 开始)。
  • 点击链接后打开了新标签页,后续代码却依然在旧页面上查找元素
    原因:带有 target="_blank" 属性的链接会在浏览器中弹出一个全新的标签页,而原本的 page 变量仍然指向旧标签页。
    解决方法:使用 context.expect_page() 捕获点击动作产生的新页面对象,后续操作切换到新变量上执行:
    with context.expect_page() as new_page_info:
        page.get_by_text("在新窗口打开详情").click()
    new_page = new_page_info.value
    new_page.wait_for_load_state()
    print("新标签页标题:", new_page.title())
  • 元素明明在页面上可见,却一直报 30 秒 TimeoutError 找不到元素
    原因:目标元素很可能被嵌套在 <iframe> 内联框架中。主页面的 page.locator() 默认不会穿透 iframe 查找内部节点。
    解决方法:先通过 page.frame_locator("#iframe-id") 定位外层框架,再链式查找内部元素,例如:page.frame_locator("#login-frame").get_by_placeholder("密码").fill("123456")。
Python Playwright自动化浏览网页的基础入门指南
图 4:Python Playwright 自动化脚本标准执行流程与各阶段高频问题排查对照
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。