首页 > 其他分享 >Playwright for .NET使用

Playwright for .NET使用

时间:2024-07-04 15:55:38浏览次数:21  
标签:Playwright await Locator 使用 var new NET page 页面

安装全局工具:

# 安装全局工具
dotnet tool install --global Microsoft.Playwright.CLI
# 创建项目
dotnet new console -n Console1
cd Console1
# 安装依赖
dotnet add package Microsoft.Playwright
# 用Playwright 工具安装所需的浏览器  C:\Users\Administrator\AppData\Local\ms-playwright
playwright install
# 运行项目
dotnet run

在新的环境中部署:

# 安装全局工具
dotnet tool install --global Microsoft.Playwright.CLI
# 用Playwright 工具安装浏览器(要在项目部署的目录)
dotnet Microsoft.Playwright.dll -- install

基本使用:

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.GotoAsync("https://www.baidu.com");
var title = await page.InnerTextAsync("title");

Playwright Trace Viewer工具来追踪测试执行:

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync(new() { Headless = true });
var context = await browser.NewContextAsync();
#region 开始追踪记录
await context.Tracing.StartAsync(new()
{
    Title = $"qwe123",
    Screenshots = true,
    Snapshots = true,
    Sources = true
});
#endregion
var page = await context.NewPageAsync();//await browser.NewPageAsync();
await page.GotoAsync("https://www.baidu.com");
//将上面链接打开后的page页面截图 保存成 screenshot.png 
await page.ScreenshotAsync(new PageScreenshotOptions { Path = Path.Combine(
        Environment.CurrentDirectory,
        "screenshot",
        $"{DateTime.Now.ToString("yyyyMMddHHmmss")}.png"
        ) });
var title = await page.InnerTextAsync("title");
#region 结束追踪记录
await context.Tracing.StopAsync(new()
{
    Path = Path.Combine(
        Environment.CurrentDirectory,
        "playwright-traces",
        $"{DateTime.Now.ToString("yyyyMMddHHmmss")}.zip"
        )
});
#endregion

Playwright Trace Viewer工具记录多个追踪(trace chunk):

using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync(new() { Headless = true });
var context = await browser.NewContextAsync();
#region 开始追踪记录
await context.Tracing.StartAsync(new()
{
    Title = $"qwe123",
    Screenshots = true,
    Snapshots = true,
    Sources = true
});
#endregion

#region 开始追踪记录
await context.Tracing.StartChunkAsync(new()
{
    Title = $"qwe123"
});
#endregion

var page = await context.NewPageAsync();//await browser.NewPageAsync();
await page.GotoAsync("https://www.baidu.com");
//将上面链接打开后的page页面截图 保存成 screenshot.png 
await page.ScreenshotAsync(new PageScreenshotOptions { Path = Path.Combine(
        Environment.CurrentDirectory,
        "screenshot",
        $"{DateTime.Now.ToString("yyyyMMddHHmmss")}.png"
        ) });
var title = await page.InnerTextAsync("title");

#region 结束追踪记录
await context.Tracing.StopChunkAsync(new()
{
    Path = Path.Combine(
        Environment.CurrentDirectory,
        "playwright-traces",
        $"{DateTime.Now.ToString("yyyyMMddHHmmss")}1.zip"
        )
});
#endregion

#region 开始追踪记录
await context.Tracing.StartChunkAsync(new()
{
    Title = $"qwe1234"
});
#endregion
await page.GotoAsync("https://www.baidu.com/");
// 等待页面加载完成
await page.WaitForLoadStateAsync(LoadState.NetworkIdle);
await page.GetByRole(AriaRole.Link, new() { Name = "登录" }).ClickAsync();
await page.GetByPlaceholder("手机号/用户名/邮箱").ClickAsync();
await page.GetByPlaceholder("手机号/用户名/邮箱").FillAsync("123456");
await page.GetByPlaceholder("密码").ClickAsync();
await page.GetByPlaceholder("密码").FillAsync("qwe123");
await page.GetByRole(AriaRole.Checkbox, new() { Name = "阅读并接受" }).CheckAsync();
await page.GetByRole(AriaRole.Button, new() { Name = "登录" }).ClickAsync();
#region 结束追踪记录

await context.Tracing.StopChunkAsync(new()
{
    Path = Path.Combine(
        Environment.CurrentDirectory,
        "playwright-traces",
        $"{DateTime.Now.ToString("yyyyMMddHHmmss")}2.zip"
        )
});
#endregion

 

本地打开跟踪文件:

playwright show-trace 12344.zip

 

开启Playwright录制操作自动生成代码脚本:

playwright codege‍

 

Playwright发布与部署:

部署模式选择“独立”,可以不依赖框架运行
另一台机器上运行我们的程序之前,需要在这台机器上重新安装 Playwright,但无需安装 dotnet 框架或运行时。
运行发布文件夹下的安装命令:

.playwright\node\win32_x64\playwright.cmd install

常用操作:

// 创建Chromium浏览器实例
await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions()
{
    Headless = false, // 关闭无头模式(有界面)
    SlowMo = 50, // 放慢执行速度
    Channel = "chrome", // 指定采用chrome浏览器类型
    Devtools = true, // 启用开发者工具
    ChromiumSandbox = false, // 关闭浏览器沙盒
    ExecutablePath = string.Empty, // 不指定浏览器可执行文件位置,会自动寻找 ms-playwright 下载的浏览器
    Args = new[] { "--enable-automation=true", "--disable-blink-features=AutomationControlled" }, // 防止selenium被检测
});
// 浏览器上下文
await using var context = await browser.NewContextAsync(new BrowserNewContextOptions
{
    ViewportSize = new ViewportSize
    {
        Width = 1536, // 1920 * 0.8
        Height = 864, // 1080 * 0.8
    }, // 窗口大小
    Locale = "zh-CN", // 指定语言(区域)
    TimezoneId = "Asia/Shanghai", // 指定时区
});
// 存储当前会话
await context.StorageStateAsync(new BrowserContextStorageStateOptions
{
    Path = "state.json"
});
// 使用会话,当state.json文件不存在时会报错
await browser.NewContextAsync(new BrowserNewContextOptions
{
    StorageStatePath = "state.json"
});
// 等待登录按钮出现
await page.WaitForSelectorAsync(".login");
// 点击登录
await page.ClickAsync(".login");
// 查找页面元素 可匹配到 <div class="title-text-n4df3g8">美食</div>
var locator = page.Locator(“div[class^='title-text-']:text-is('美食')”);
// 获取匹配到元素的个数
var count = await locator.CountAsync();
// 鼠标悬停在元素上
await page.HoverAsync("#title");
// 执行js获取页面地址
var href = await page.EvaluateAsync<string>("document.location.href");
// 定位器
var element = page.Locator(".passMod_dialog-close-btn");
// 等待1秒
await Task.Delay(1000);
await element.ClickAsync();

// 显式等待 设定的超时时间内,仍然没有通过定位器等待到目标元素,将会抛出异常
await page.GotoAsync("https://stackoverflow.com/");
var elelment = page.Locator("id=noscript-warning");
await elelment.WaitForAsync();
var text = await elelment.InnerTextAsync(new LocatorInnerTextOptions { Timeout = 10 });

// RunAndWaitForPopupAsync 方法可以帮助我们执行操作并等待弹出窗口出现
await page.GotoAsync("https://www.baidu.com/");
await page.RunAndWaitForPopupAsync(async () =>
{
    await page.ClickAsync("text=新闻");
},
    new PageRunAndWaitForPopupOptions
    {
        Predicate = (page) =>
        {
            return page.Url.Contains("news.baidu.com");
        }
    });

// RunAndWaitForRequestAsync/RunAndWaitForResponseAsync两个方法可以通过传入URL地址或表达式来过滤等待的请求或响应,从而实现更加精细的控制。方法都是阻塞式的。也就是说,如果我们等待的情况一直未出现,后续的代码将不会执行。
// 在某些情况下,我们只需要在情况出现时进行一些操作,即使情况不出现也不应该影响整体的运行。这时,我们可以使用监听事件来实现。 await page.RunAndWaitForRequestAsync(async () => { await page.GotoAsync("https://stackoverflow.com/", new PageGotoOptions{ WaitUntil = WaitUntilState.Commit}); }, request => { Console.WriteLine(request.Url); //return request.Url.Contains("jquery.min.js"); return request.Url.Contains("stacks.min.js"); }); await page.RunAndWaitForResponseAsync(async () => { await page.ClickAsync("text='Login'"); }, response => response.Url.Contains("users/login") ); // 当页面发起的请求失败时触发 page.RequestFailed += (sender, request) => { Console.WriteLine($"请求{request.Url}发生错误{request.Failure}"); }; // 当页面发起的请求完成时触发 page.RequestFinished += (sender, request) => { Console.WriteLine($"请求{request.Url}发生错111111误{request.Failure}"); }; await page.GotoAsync("https://baidu.com/"); // Close:当页面关闭时触发 // Console:当控制台输出时触发 // Crash:当页面崩溃时触发。例如,试图分配太多内存,浏览器页面可能会崩溃。 // Dialog:当 JavaScript 对话框出现时触发。例如,alert、prompt、confirm等。 // DOMContentLoaded:当页面的 DOMContentLoaded 事件触发时触发 // Download:当下载开始时触发 // FileChooser:当文件选择对话框出现时触发 // FrameAttached:当 frame 连接到页面时触发 // FrameDetached:当 frame 与页面分离时触发 // FrameNavigated:当 frame 导航到一个新的 url 时触发 // Load: 当页面的 load 事件触发时触发 // PageError:当页面内发生未捕获异常时触发 // Popup:当页面弹出新的窗口时触发 // Request:当页面发起一个新的请求时触发 // RequestFailed:当页面发起的请求失败时触发 // RequestFinished:当页面发起的请求完成时触发 // Response:当页面收到一个新的响应时触发 // 输入搜索关键字 await page.TypeAsync("input[name='q1']", "关键字"); // 点击page按钮跳转到page1 var page1 = await page.RunAndWaitForPopupAsync(async () => { // 点击搜索 await page.ClickAsync(".advanced-search-btn"); }); // 检查文本框内容 var handleInput = await page1.WaitForSelectorAsync("#kw"); var text = await handleInput.GetAttributeAsync("value"); // 输入操作 await page.Locator("#kw").FillAsync("1212121"); // 点击操作 await page.Locator("#kw").ClickAsync(); // 单选(选中,已选中状态下无效) await page.Locator(".check1").SetCheckedAsync(true); await page.Locator(".Volvo").CheckAsync(); // 复选框(选中,已选中状态下无效) await page.Locator("#checkbox [type='checkbox']:nth-child(7)").CheckAsync(); await page.Locator("#checkbox [type='checkbox']:nth-child(7)").SetCheckedAsync(true); // 下拉框操作 // 选择下拉框中的选项 await page.SelectOptionAsync("select[name='country']", "Canada"); // 通过value值选择 await page.Locator("[name='select']").SelectOptionAsync("opel"); // 通过可见文本选择 await page.Locator("[name='select']").SelectOptionAsync(new SelectOptionValue { Label = "blue" }); // 多个选定项目 await page.GetByLabel("Choose multiple colors").SelectOptionAsync(new[] { "blue", "green", "red" }); // 常规单击 await page.Locator("#mouse2").ClickAsync(); // 单击 await page.GetByRole(AriaRole.Button).ClickAsync(); // 双击 await page.GetByText("Item").DblClickAsync(); // 右击 await page.GetByText("Item").ClickAsync(new() { Button = MouseButton.Right }); // Shift + click await page.GetByText("Item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.Shift } }); // Ctrl + click or Windows and Linux // Meta + click on macOS await page.GetByText("Item").ClickAsync(new() { Modifiers = new[] { KeyboardModifier.ControlOrMeta } }); // Hover over element await page.GetByText("Item").HoverAsync(); // Click the top left corner await page.GetByText("Item").ClickAsync(new() { Position = new Position { X = 0, Y = 0 } }); //上传一个文件 await page.Locator("#load").SetInputFilesAsync("demo.md"); // 上传多个文件 await page.Locator("#load").SetInputFilesAsync(new[] { "file1.txt", "file12.txt" }); // 上传文件 找到文件上传输入框 var fileInput = await page.QuerySelectorAsync("input[type='file']"); string filePath = "path/to/your/file.txt"; // 你要上传的文件路径 await fileInput.SetInputFilesAsync(filePath); // 提取页面标题 string title = await page.TitleAsync(); title = await page.InnerTextAsync("title"); Console.WriteLine("Page title: " + title); // 提取页面 URL string url = page.Url; Console.WriteLine("Page URL: " + url); // 提取特定元素的文本内容 var elementText = await page.EvaluateAsync<string>("document.querySelector('h1').textContent"); Console.WriteLine("Header text: " + elementText); // 提取页面中的链接 var links = await page.QuerySelectorAllAsync("a"); foreach (var link in links) { var href = await link.GetAttributeAsync("href"); Console.WriteLine("Link: " + href); } // 等待表格加载完毕 await page.WaitForSelectorAsync("table"); // 获取表格内容 var tableHtml = await page.InnerHTMLAsync("table"); // 使用正则表达式提取表格数据 var regex = new Regex(@"<tr>(.*?)</tr>"); var matches = regex.Matches(tableHtml); foreach (Match match in matches) { // 这里可以根据表格结构和需要自行解析数据 var rowHtml = match.Groups[1].Value; Console.WriteLine("Row HTML: " + rowHtml); } // 等待页面加载完成 await page.WaitForLoadStateAsync(LoadState.NetworkIdle); // 等待页面跳转 await page.WaitForNavigationAsync(); // RunAndWaitForFileChooserAsync 方法可以帮助我们在执行操作的同时等待文件选择器的出现。 await page.GotoAsync("https://image.baidu.com/"); await page.RunAndWaitForFileChooserAsync(async () => { await page.ClickAsync("id=sttb"); await page.ClickAsync("id=uploadImg"); }, new PageRunAndWaitForFileChooserOptions { Predicate = (fileChooser) => { return !fileChooser.IsMultiple; } }); // RunAndWaitForNavigationAsync 方法可以帮助我们执行操作并等待页面导航完成 await page.GotoAsync("https://stackoverflow.com/"); await page.RunAndWaitForNavigationAsync(async () => { await page.ClickAsync("text='Log in'"); }, new PageRunAndWaitForNavigationOptions { UrlFunc = (url) => { return url.Contains("users/login"); }, WaitUntil = WaitUntilState.Commit }); // JavaScript互操作 await page.ExposeFunctionAsync("sha256", (string input) => { return Convert.ToBase64String( SHA256.Create().ComputeHash(System.Text.Encoding.UTF8.GetBytes(input))); }); await page.SetContentAsync(@"<script> async function onClick() { document.querySelector('div').textContent = await window.sha256('PLAYWRIGHT'); } </script> <button onclick='onClick()'>Click me</button> <div></div>" ); await page.ClickAsync("button"); // Locator(定位器) // 按 id 查找 page.Locator("#su"); page.Locator("id=su"); // 按文本查找 page.Locator("text=hao123"); page.Locator("'hao123'"); page.Locator("text=/^ha\\w+23$/i"); // 按 CSS 查找 page.Locator("input[value='百度一下']"); page.Locator("input:text('百度')"); //按 XPath 查找 page.Locator("//*[@id=\"su\"]"); // BrowserContext(浏览器上下文) var browserContext1 = await browser.NewContextAsync(); var cookie1 = await GetCookie(browserContext1); Console.WriteLine(cookie1); var browserContext2 = await browser.NewContextAsync(); var cookie2 = await GetCookie(browserContext2); Console.WriteLine(cookie2); static async Task<string> GetCookie(IBrowserContext browserContext) { var page = await browserContext.NewPageAsync(); await page.GotoAsync("https://www.baidu.com"); var cookies = await browserContext.CookiesAsync(); return cookies.First(p => p.Name == "BAIDUID").Value; } // Frame(框架) foreach (var frame in page.Frames) Console.WriteLine($"{frame.Url.Split('/').Last()}"); Console.WriteLine(""); Console.WriteLine("显示 Frame 嵌套树:"); DumpFrameTree(page.MainFrame, string.Empty); static void DumpFrameTree(IFrame frame, string indent) { Console.WriteLine($"{indent}{frame.Url.Split('/').Last()}"); foreach (var child in frame.ChildFrames) DumpFrameTree(child, indent + " "); }

 

设置playwright环境的默认目录:

Environment.SetEnvironmentVariable("PLAYWRIGHT_BROWSERS_PATH", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ms-playwright"));
//初始化playwright环境,chromium, chrome, chrome-beta, msedge, msedge-beta, msedge-dev, firefox, webkit 可选
Microsoft.Playwright.Program.Main(new[] { "install", "chromium" });

 

标签:Playwright,await,Locator,使用,var,new,NET,page,页面
From: https://www.cnblogs.com/sanday/p/18283994

相关文章

  • 使用g++对c++进行编译链接
    静态库静态库的生成静态库实际就是多个.o的归档(文件夹)//在bash终端执行依次执行以下g++命令.g++-csrc1.cppsrc2.cpparcrvlibmy.asrc1.osrc2.o查看静态库内容://输出src1.0,src2.0,这也验证了静态库.a文件实际就是个归档目录ar-tlibmy.a......
  • 使用教程
    一、概述本产品能够实现两点之间的P2P直连内网穿透,不用通过中继服务器提供流量中转服务。本产品采用了最先进的P2P算法,即便对称型NAT在内的大多数连接也可实现P2P通讯。因为在数据传无需中继服务器作为中转,具有强劲的传输速度和安全性。数据在传输过程中采用各类加密传输......
  • 怎么使用零代码平台,在线搭建一套应用系统 — 敲敲云免费
    应用基础操作:包含创建应用、修改应用、退出/删除应用、排序应用、维护应用、应用回收站1、新建应用进入你的组织,点击左侧的应用,然后点击新建应用新建应用的创建者为应用的拥有者,默认拥有管理员权限2、修改应用名称和主题应用中点击...,找到修改名称和主题,点击即可,支持......
  • java 事件回调的写法,使用回调接口方式
    java编写时,尤其是先用C#语言后转成java的,在编程时一定会遇到,java中没有委托事件的概念。那主类App.java类中实例了一个A对象,那A对象因为某种原因触发了一个事件,想回调App.java中的一个函数,应该怎么写呢?在java中有多有方法来实现,这里讲下回调接口方式,我感觉这种方式比较好理解......
  • C语言函数静态库和动态库的创建和使用
    使用库函数是源码的一种保护???<我猜的.>库函数其实不是新鲜的东西,我们一直都在用,比如C库.我们执行pringf()这个函数的时候,就是调用C库的函数. 下面记录静态库和动态库的生成和使用. 静态库:libxxx.a动态库:libxxx.so 静态库: 在程序编译的时候,将库编译进可......
  • HTML5 WebSocket技术使用详解
    HTML5WebSocketAPI提供了一种在单个连接上进行全双工通信的方式。这意味着客户端和服务器可以同时发送和接收数据,而不需要像传统的HTTP请求那样进行多次请求和响应的轮询。WebSocket允许更实时的交互,非常适合需要快速、连续数据交换的应用场景,如在线游戏、实时通讯和股票行......
  • 详解Web应用安全系列(7)使用具有已知漏洞的组件
    使用具有已知漏洞的组件,这种安全漏洞普遍存在,基于组件开发的模式使得多数开发团队根本不了解其应用或API中使用的组件,更谈不上及时更新这些组件了。下面就分别以.NET和Java各分享一个案例。.NET案例:XmlSerializer反序列化漏洞案例描述在.NET框架中,XmlSerializer类是一个常......
  • 前端-vue工程化-Pinia的使用
    先来看一下我们的文件夹吧:大多数vue3前端项目中都会有这样一个文件夹是用来存放全局变量的地方,用来做状态管理。我们项目中使用的状态管理工具其实就是Pinia,当然不是我推荐大家用的,这个有迹可循,因为Pinia是在Vue官网上被推荐的一种方式。下面截几张官网上的图片:然后给......
  • 在Linux中,可以使用哪个命令查看系统的历史负载?
    在Linux中,你可以使用top命令或uptime命令来查看系统的历史负载。top命令:top命令是一个实时的系统监控工具,它可以显示系统进程的动态实时视图,包括CPU和内存的使用情况。要查看历史负载,你可以在top命令中按Shift+H(在某些版本中可能是H)来切换显示模式,显示所有CPU的平均负载,而不......
  • 使用 EFCore简单入门(实体类生成数据库表)
    1.安装Nuget包Microsoft.EntityFrameworkCore.SqlServerMicrosoft.EntityFrameworkCore.Tools2.创建Book,Post两个实体类publicclassBook{///<summary>///id///</summary>publicintId{get;set;}///<summary>///......