适用于 PowerShell 7.0 及以上版本
背景 2026 年,浏览器自动化技术已经从简单的网页测试工具发展为 AI Agent 执行任务的核心能力。以 Browser Use 为代表的框架让 AI 模型能够直接操控浏览器完成复杂任务,例如自动填表、数据采集、跨站点流程编排等。Playwright 和 Selenium 作为两大主流浏览器自动化引擎,都提供了成熟的 API,而 PowerShell 凭借其强大的对象管道和 .NET 生态集成能力,成为串联这些工具的绝佳胶水语言。
在实际运维和数据处理场景中,我们经常需要从没有 API 的内部系统中提取数据、定时提交报表、或批量执行重复的网页操作。传统做法依赖手动操作或录制宏脚本,维护成本高且容易出错。PowerShell 结合 Playwright 可以编写声明式的自动化脚本,配合 AI 模型甚至能实现”说一句话,浏览器自动完成操作”的智能体验。
本文将分三个层次介绍 PowerShell 浏览器自动化:从 Playwright 基础操作,到数据采集与表单自动化,再到 AI 驱动的智能浏览器操作,帮助读者逐步掌握这项实用技能。
Playwright 自动化基础 Playwright 是微软开发的跨浏览器自动化框架,原生支持 Chromium、Firefox 和 WebKit。PowerShell 可以通过 .NET 互操作直接调用 Playwright 的 NuGet 包,实现从浏览器启动到元素操作的全流程控制。
以下代码演示了 Playwright 的安装、浏览器启动、页面导航、等待元素加载、点击按钮、读取文本等基本操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Install-Module -Name Microsoft.Playwright -Scope CurrentUser -Force dotnet tool install --global Microsoft.Playwright.CLI playwright install chromium using module Microsoft.Playwright$playwright = [Microsoft.Playwright.Program ]::CreatePlaywright()$browser = $playwright .Chromium.LaunchAsync(@ { headless = $true }).GetAwaiter().GetResult()$page = $browser .NewPageAsync().GetAwaiter().GetResult()$page .GotoAsync("https://example.com" ).GetAwaiter().GetResult()$page .WaitForSelectorAsync("h1" ).GetAwaiter().GetResult() | Out-Null $title = $page .TextContentAsync("h1" ).GetAwaiter().GetResult()Write-Host "页面标题: $title " $links = $page .QuerySelectorAllAsync("a" ).GetAwaiter().GetResult()foreach ($link in $links ) { $href = $link .GetAttributeAsync("href" ).GetAwaiter().GetResult() $text = $link .TextContentAsync().GetAwaiter().GetResult() Write-Host " 链接: $text -> $href " } $browser .CloseAsync().GetAwaiter().GetResult()$playwright .Dispose()
执行结果示例:
1 2 页面标题: Example Domain 链接: More information... -> https://www.iana.org/domains/example
在实际项目中,推荐使用 try-finally 块确保浏览器资源被正确释放,避免残留进程占用系统内存。
数据采集与表单自动化 网页数据提取和表单自动填写是浏览器自动化最常见的应用场景。PowerShell 可以将采集到的结构化数据直接转化为对象,利用管道进行筛选和导出,这是其他脚本语言难以比拟的优势。
下面的脚本展示了从网页表格提取数据、自动填写搜索表单、以及将页面保存为截图和 PDF 的完整流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 using module Microsoft.Playwright$playwright = [Microsoft.Playwright.Program ]::CreatePlaywright()$browser = $playwright .Chromium.LaunchAsync(@ { headless = $true }).GetAwaiter().GetResult()$page = $browser .NewPageAsync().GetAwaiter().GetResult()$page .GotoAsync("https://example.com/tables" ).GetAwaiter().GetResult()$page .WaitForSelectorAsync("table" ).GetAwaiter().GetResult() | Out-Null $rows = $page .QuerySelectorAllAsync("table tbody tr" ).GetAwaiter().GetResult()$tableData = foreach ($row in $rows ) { $cells = $row .QuerySelectorAllAsync("td" ).GetAwaiter().GetResult() [PSCustomObject ]@ { Name = $cells [0 ].TextContentAsync().GetAwaiter().GetResult().Trim() Value = $cells [1 ].TextContentAsync().GetAwaiter().GetResult().Trim() Status = $cells [2 ].TextContentAsync().GetAwaiter().GetResult().Trim() } } $tableData | Where-Object { $_ .Status -eq "Active" } | Export-Csv -Path "active_items.csv" -NoTypeInformation -Encoding utf8Write-Host "已导出 $ ($tableData .Count) 条记录" $page .GotoAsync("https://example.com/search" ).GetAwaiter().GetResult()$page .FillAsync("#search-input" , "PowerShell automation" ).GetAwaiter().GetResult()$page .SelectOptionAsync("#category" , "technology" ).GetAwaiter().GetResult()$page .ClickAsync("#search-button" ).GetAwaiter().GetResult()$page .WaitForSelectorAsync(".result-item" ).GetAwaiter().GetResult() | Out-Null $page .ScreenshotAsync(@ { path = "search-results.png" ; fullPage = $true }).GetAwaiter().GetResult() | Out-Null Write-Host "截图已保存到 search-results.png" $page .PdfAsync(@ { path = "search-results.pdf" ; format = "A4" }).GetAwaiter().GetResult() | Out-Null Write-Host "PDF 已保存到 search-results.pdf" $browser .CloseAsync().GetAwaiter().GetResult()$playwright .Dispose()
执行结果示例:
1 2 3 已导出 12 条记录 截图已保存到 search-results.png PDF 已保存到 search-results.pdf
通过 PSCustomObject 将网页数据结构化后,可以无缝使用 Where-Object、Sort-Object、Export-Csv 等 PowerShell 原生命令进行后续处理,实现从采集到入库的一体化流程。
AI 驱动的浏览器操作 2026 年最具变革性的趋势是将大语言模型(LLM)与浏览器自动化结合,让 AI 理解页面语义后自动决定操作步骤。PowerShell 在这个场景中扮演调度器的角色:调用 LLM API 分析页面结构,解析返回的指令,再驱动浏览器执行具体动作。
以下脚本展示了如何用 PowerShell 调用本地 Ollama 模型分析网页元素,实现 AI 驱动的智能浏览器操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 using module Microsoft.Playwright$ollamaEndpoint = "http://localhost:11434/api/generate" $modelName = "qwen2.5:7b" function Invoke-OllamaChat { param ([string ]$Prompt ) $body = @ { model = $modelName prompt = $Prompt stream = $false } | ConvertTo-Json -Depth 5 $response = Invoke-RestMethod -Uri $ollamaEndpoint -Method Post -Body $body -ContentType "application/json" return $response .response } $playwright = [Microsoft.Playwright.Program ]::CreatePlaywright()$browser = $playwright .Chromium.LaunchAsync(@ { headless = $false }).GetAwaiter().GetResult()$page = $browser .NewPageAsync().GetAwaiter().GetResult()$page .GotoAsync("https://news.example.com" ).GetAwaiter().GetResult()$elements = $page .QuerySelectorAllAsync("a, button, input, select" ).GetAwaiter().GetResult()$elementSummary = foreach ($el in $elements [0 ..19 ]) { $tag = $el .EvaluateHandleAsync("e => e.tagName" ).GetAwaiter().GetResult().JsonValue $text = $el .TextContentAsync().GetAwaiter().GetResult() $role = $el .GetAttributeAsync("role" ).GetAwaiter().GetResult() " <$tag > text='$ ($text .Trim().Substring(0, [Math]::Min(50, $text .Trim().Length)))' role='$role '" } $summaryText = $elementSummary -join "`n" $aiPrompt = @" 你是一个浏览器自动化助手。以下是页面上的可交互元素: $summaryText 用户任务:找到今天浏览量最高的科技新闻标题。 请告诉我应该点击哪个元素(用序号表示),以及后续操作建议。 只返回简洁的操作指令,不要解释。 "@ $aiResponse = Invoke-OllamaChat -Prompt $aiPrompt Write-Host "AI 建议: $aiResponse " if ($aiResponse -match "点击.*?(\d+)" ) { $index = [int ]$Matches [1 ] if ($index -lt $elements .Count) { $elements [$index ].ClickAsync().GetAwaiter().GetResult() | Out-Null Write-Host "已执行 AI 建议的点击操作(元素 #$index )" } } Start-Sleep -Seconds 2 $articleTitle = $page .TitleAsync().GetAwaiter().GetResult()Write-Host "当前页面标题: $articleTitle " $browser .CloseAsync().GetAwaiter().GetResult()$playwright .Dispose()
执行结果示例:
1 2 3 AI 建议: 点击元素 #3,这是"科技"分类链接。进入后点击第一个新闻标题即可。 已执行 AI 建议的点击操作(元素 #3) 当前页面标题: 最新科技新闻 - News Example
这种方式将 LLM 的语义理解能力与 Playwright 的精确操作能力结合,实现了”自然语言到浏览器操作”的闭环。在生产环境中,建议加入操作确认机制和异常回退逻辑,确保 AI 的操作可预测且可追溯。
注意事项
资源管理 :Playwright 的浏览器实例是重量级资源,务必使用 try-finally 块确保 CloseAsync 和 Dispose 被调用,避免残留进程消耗系统资源。
异步处理 :Playwright 的 .NET API 大量使用 async/await 模式,在 PowerShell 中需要通过 .GetAwaiter().GetResult() 同步等待。避免在循环中频繁调用,可改用批量操作减少开销。
等待策略 :页面加载时间受网络状况影响较大,推荐使用 WaitForSelectorAsync 替代固定的 Start-Sleep,既保证元素可用,又避免不必要的等待。
无头模式选择 :开发调试时使用 headless = $false 以便观察浏览器行为,生产环境使用 headless = $true 提升性能。在 Linux 服务器上运行时需要安装额外的系统依赖库。
AI 操作安全性 :让 LLM 直接控制浏览器操作具有不确定性,务必对 AI 返回的指令进行校验(如索引范围检查、URL 白名单过滤),防止误操作导致数据丢失或安全风险。
反爬虫应对 :部分网站会检测自动化工具并限制访问。可通过设置 User-Agent、使用浏览器上下文隔离、控制请求频率等方式降低被识别的概率,同时确保遵守目标网站的服务条款。