Puppeteer的安装与使用

为了实现UI自动化测试,在web端的应用,而做的一次调研。由于原项目自动化框架是基于C#,所以研究了Puppeteer在Visual Studio 2019上如何安装和使用。


WebView2

Microsoft Edge WebView2 控件允许在本机应用中嵌入 web 技术(HTML、CSS 以及 JavaScript)。 WebView2 控件使用 Microsoft Edge 作为绘制引擎,以在本机应用中显示 web 内容。

使用 WebView2 可以在本机应用的不同部分嵌入 Web 代码,或在单个 WebView2 实例中生成所有本机应用。

在这里插入图片描述

Puppeteer与PuppeteerSharp

  1. Puppeteer 是一个Chrome官方团队提供的node库,它可以通过 Puppeteer 的提供的 API 直接控制 Chrome 或 Chromiun。
  2. Puppeteer Sharp是官方Node.JS Puppeteer API的.NET移植。本文主要介绍使用Puppeteer Sharp方法代码和文档。可以生成网页截图,将网页保存成pdf文件,执行Javascript(js)代码等。

提示:以下是本篇文章正文内容,下面案例可供参考

一、Puppeteer可以做什么

1) 生成网页截图或者 PDF
2) 爬取SPA应用,并生成预渲染内容(即“SSR” 服务端渲染)
3) 高级爬虫,可以爬取大量异步渲染内容的网页
4) 模拟键盘输入、表单自动提交、登录网页等
5) 创建一个最新的自动化测试环境,实现 UI 自动化测试
6) 捕获站点的时间线,以便追踪网站、帮助分析网站性能问题
7) 用于测试 Chrome 扩展程序

二、Puppeteer 架构图

在这里插入图片描述
Puppeteer API 是分层的,并反映了浏览器的结构。

  • Puppeteer 使用 DevTools Protocol 与浏览器通信
  • Browser 实例可以拥有多个浏览器上下文
  • BrowserContext实例定义了一个浏览会话,可以拥有多个页面
  • Page至少有一个 frame :main frame。可能还有其他由 iframe 创建的 frame 或标签
  • Frame至少有一个可执行上下文 - 默认执行上下文 - 在其中执行 frame 的 JavaScript 。一个 Frame 可能有与 extensions 有关联的其他执行上下文
  • Worker具有单个执行上下文,便于与 WebWorkers 交互

三、示例

安装PuppeteerSharp

Nuget是一个.NET平台下的开源的项目,它是Visual Studio的扩展。在使用Visual Studio开发基于.NET
Framework的应用时,Nuget能把在项目中添加、移除和更新引用的工作变得更加快捷方便。
NuGet能更方便地把一些dll和文件(如jquery)添加到项目中,而不需要从文件中复制拷贝。说简单点,就是Nuget可以自动管理.NET项目依赖关系,但是项目要打包成Nuget包。vs2019可以直接发布生成Nuget包。Nuget包放在自已的Nuget服务器上,或者官方的Nuget服务器上。

1.打开NuGet包管理,点击第二个>>管理解决方案的NuGet
在这里插入图片描述
2.搜索puppeteer,下载在这里插入图片描述

1.获取百度网页生成PDF,代码如下(示例):

using System;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using PuppeteerSharp;//引入库
namespace Class_learn
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            //启动Chrome/ium浏览器的选项。
            var options = new LaunchOptions
            {
                Headless = true
            };

            Console.WriteLine("Downloading chromium");
            //初始化PuppeteerSharp的一个新实例。BrowserFetcher类。
            using var browserFetcher = new BrowserFetcher();
            //下载修订版本。解析完成下载的任务。
            await browserFetcher.DownloadAsync();

            Console.WriteLine("Navigating baidu");
            //该方法使用给定的参数启动一个浏览器实例。浏览器将在浏览器被释放时关闭。
            using (var browser = await Puppeteer.LaunchAsync(options))
            //创建新页面
            //任务解析为一个新的PuppeteerSharp。页面对象
            using (var page = await browser.NewPageAsync())
            {
                await page.GoToAsync("http://www.baidu.com");

                Console.WriteLine("Generating PDF");
                await page.PdfAsync(Path.Combine(Directory.GetCurrentDirectory(), "baidu.pdf"));

                Console.WriteLine("Export completed");

                if (!args.Any(arg => arg == "auto-exit"))
                {
                    Console.ReadLine();
                }
            }
        }
    }
}

结果

控制台结果
生成的PDF
生成的本地地址

2.获取百度网页生成图片,并改变大小,代码如下(示例):

using System;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using PuppeteerSharp;
namespace Class_learn
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            var options = new LaunchOptions
            {
                Headless = true
            };

            Console.WriteLine("Downloading chromium");
            using var browserFetcher = new BrowserFetcher();
            await browserFetcher.DownloadAsync();

            Console.WriteLine("Navigating baidu");
            using (var browser = await Puppeteer.LaunchAsync(options))
            using (var page = await browser.NewPageAsync())
            {
                await page.GoToAsync("http://www.baidu.com");

                Console.WriteLine("Generating Picture");
                //await page.PdfAsync(Path.Combine(Directory.GetCurrentDirectory(), "baidu.pdf"));
				//改变图片大小应该放在输出之前
				//设置视口。在一个浏览器中有多个页面的情况下,每个页面
                //可以有自己的视口大。PuppeteerSharp.Page.SetViewportAsync (PuppeteerSharp.ViewPortOptions)
//将调整页面大小。很多网站都不希望手机改变尺寸,所以应该在导航到页面之前设置视口。
                await page.SetViewportAsync(new ViewPortOptions
                {
                    Width = 2000,
                    Height = 600
                });
                await page.ScreenshotAsync(Path.Combine(Directory.GetCurrentDirectory(), "baidu.png"));
                
                Console.WriteLine("Export completed");

                if (!args.Any(arg => arg == "auto-exit"))
                {
                    Console.ReadLine();
                }
            }
        }
    }
}

ViewPortOptions设置参数
在这里插入图片描述

默认结果
在这里插入图片描述
改变后
在这里插入图片描述

3.向网页中注入HTML

using System;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using PuppeteerSharp;
namespace Class_learn
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            var options = new LaunchOptions
            {
                Headless = true
            };

            Console.WriteLine("Downloading chromium");
            using var browserFetcher = new BrowserFetcher();
            await browserFetcher.DownloadAsync();

            Console.WriteLine("Navigating baidu");
            using (var browser = await Puppeteer.LaunchAsync(options))
            using (var page = await browser.NewPageAsync())
            {
                await page.SetContentAsync("<div>My Receipt</div>");
                //获取页面的完整HTML内容,包括文档类型。
                var result = await page.GetContentAsync();
                await page.PdfAsync(Path.Combine(Directory.GetCurrentDirectory(), "test.pdf"));
                Console.WriteLine(result);
                Console.WriteLine("Export completed");

                if (!args.Any(arg => arg == "auto-exit"))
                {
                    Console.ReadLine();
                }
            }
        }
    }
}

结果

在这里插入图片描述
在这里插入图片描述

4.从一个页面获得所有的Href链接

这个示例演示了如何从页面获取链接。

using System;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using PuppeteerSharp;

using System.Diagnostics;


namespace Class_learn
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var options = new LaunchOptions { Headless = true };
            Console.WriteLine("Downloading chromium");
            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
            Console.WriteLine("Navigating to baidu.com");

            using (var browser = await Puppeteer.LaunchAsync(options))
            using (var page = await browser.NewPageAsync())
            {
                await page.GoToAsync("http://www.baidu.com");
                var jsSelectAllAnchors = @"Array.from(document.querySelectorAll('a')).map(a => a.href);";
                var urls = await page.EvaluateExpressionAsync<string[]>(jsSelectAllAnchors);
                foreach (string url in urls)
                {
                    Console.WriteLine($"Url: {url}");
                }
                Console.WriteLine("Press any key to continue...");
                Console.ReadLine();
            }
        }
    }
}

结果

Downloading chromium
Navigating to baidu.com
Url: https://www.baidu.com/
Url: javascript:;
Url: https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F&sms=5
Url: http://news.baidu.com/
Url: https://www.hao123.com/?src=from_pc
Url: http://map.baidu.com/
Url: http://tieba.baidu.com/
Url: https://haokan.baidu.com/?sfrom=baidu-top
Url: http://image.baidu.com/
Url: https://pan.baidu.com/?from=1026962h
Url: http://www.baidu.com/more/
Url: http://fanyi.baidu.com/
Url: http://xueshu.baidu.com/
Url: https://wenku.baidu.com/
Url: https://baike.baidu.com/
Url: https://zhidao.baidu.com/
Url: https://jiankang.baidu.com/widescreen/home
Url: http://e.baidu.com/ebaidu/home?refer=887
Url: https://live.baidu.com/
Url: http://music.taihe.com/
Url: http://www.baidu.com/more/
Url: https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F&sms=5
Url: javascript:;
Url: javascript:;
Url: https://www.baidu.com/
Url: javascript:;
Url: javascript:;
Url: javascript:;
Url: https://top.baidu.com/board?platform=pc&sa=pcindex_entry
Url:
Url: https://www.baidu.com/s?wd=40%E7%A7%92%E6%B2%89%E6%B5%B8%E5%BC%8F%E7%9C%8B%E9%97%AE%E5%A4%A9%E5%87%BA%E5%BE%81&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=super&cl=3&tn=baidutop10&fr=top1000&rsv_idx=2&hisfilter=1
Url: https://www.baidu.com/s?wd=%E5%AE%9E%E4%BD%93%E7%BB%8F%E6%B5%8E%E6%81%A2%E5%A4%8D%E5%90%91%E5%A5%BD%E9%9F%A7%E6%80%A7%E5%BC%BA&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=super&cl=3&tn=baidutop10&fr=top1000&rsv_idx=2&hisfilter=1
Url: https://www.baidu.com/s?wd=%E4%B8%A4%E5%B2%81%E5%A5%B3%E7%AB%A5%E6%82%A3%E5%B0%96%E9%94%90%E6%B9%BF%E7%96%A3%EF%BC%9F%E8%AD%A6%E6%96%B9%E5%B7%B2%E4%BB%8B%E5%85%A5&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=super&cl=3&tn=baidutop10&fr=top1000&rsv_idx=2&hisfilter=1
Url: https://www.baidu.com/s?wd=%E4%B8%AD%E6%96%B9%E5%9B%9E%E5%BA%94%E4%BD%A9%E6%B4%9B%E8%A5%BF%E6%8B%9F%E8%AE%BF%E5%8F%B0%EF%BC%9A%E4%B8%A5%E9%98%B5%E4%BB%A5%E5%BE%85&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=super&cl=3&tn=baidutop10&fr=top1000&rsv_idx=2&hisfilter=1
Url: https://www.baidu.com/s?wd=%E6%9E%97%E5%BF%97%E9%A2%96%E7%9B%AE%E5%89%8D%E6%84%8F%E8%AF%86%E6%B8%85%E6%A5%9A+%E8%83%BD%E7%AE%80%E5%8D%95%E5%AF%B9%E8%AF%9D&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=super&cl=3&tn=baidutop10&fr=top1000&rsv_idx=2&hisfilter=1
Url: https://www.baidu.com/s?wd=%E7%94%B7%E5%AD%A9%E5%9B%A0%E4%B8%8B%E6%A3%8B%E7%8A%AF%E8%A7%84%E8%A2%AB%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%8A%98%E6%96%AD%E6%89%8B%E6%8C%87&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=super&cl=3&tn=baidutop10&fr=top1000&rsv_idx=2&hisfilter=1
Url: https://home.baidu.com/
Url: http://ir.baidu.com/
Url: http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11000002000001
Url: https://beian.miit.gov.cn/
Url: https://www.baidu.com/licence/
Url: https://www.baidu.com/duty
Url: https://help.baidu.com/
Url: https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news
Url: http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&ie=utf-8
Url: http://image.baidu.com/i?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8
Url: http://zhidao.baidu.com/q?ct=17&pn=0&tn=ikaslist&rn=10&fr=wwwt
Url: http://wenku.baidu.com/search?lm=0&od=0&ie=utf-8
Url: http://tieba.baidu.com/f?fr=wwwt
Url: https://map.baidu.com/?newmap=1&ie=utf-8&s=s
Url: https://b2b.baidu.com/s?fr=wwwt
Url: http://www.baidu.com/more/
Press any key to continue...

5.从网站上抓取搜索结果。本例搜索developers.google.com/web
获取标记为“Headless Chrome”的文章,并从结果页面中获取结果。

// 声明应用用到的命名空间
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Dynamic;
using System.Linq.Expressions;
using System.Net;
using System.IO;
using System.Diagnostics;
using PuppeteerSharp;
namespace Lenarn_Csharp
{
    class Program
    {
        /// <summary>
        /// 从网站上抓取搜索结果
        /// 本例搜索developers.google.com/web
        /// 获取标记为“Headless Chrome”的文章,并从结果页面中获取结果。
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public static async Task Main(string[] args)
        {
            var options = new LaunchOptions { Headless = true };
            Console.WriteLine("Downloading chromium");

            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
            Console.WriteLine("Navigating to developers.google.com");

            using (var browser = await Puppeteer.LaunchAsync(options))
            using (var page = await browser.NewPageAsync())
            {
                await page.GoToAsync("https://developers.google.com/web/");
                // Type into search box.在搜索框中键入
                await page.TypeAsync("input.devsite-search-field.devsite-search-query", "Headless Chrome");

                // Wait for suggest overlay to appear and click "show all results".
                // 等待“建议覆盖”出现,然后单击“显示所有结果”。
                var allResultsSelector = ".devsite-suggest-all-results";
                await page.WaitForSelectorAsync(allResultsSelector);
                await page.ClickAsync(allResultsSelector);

                // Wait for the results page to load and display the results.
                // 等待结果页面加载并显示结果。
                var resultsSelector = "a.gs-title";
                await page.WaitForSelectorAsync(resultsSelector);
                var links = await page.EvaluateFunctionAsync(@"(resultsSelector) => {
    const anchors = Array.from(document.querySelectorAll(resultsSelector));
    return anchors.map(anchor => {
      const title = anchor.textContent.split('|')[0].trim();
      return `${title} - ${anchor.href}`;
    });
}", resultsSelector);

                foreach (var link in links)
                {
                    Console.WriteLine(link);
                }

                Console.WriteLine("Press any key to continue...");
                Console.ReadLine();
		    }
		}
	}
}
    
    
        

结果

在这里插入图片描述
在这里插入图片描述

6.在无头浏览器中成功加载网页后,让我们通过搜索本地旅游景点与网页进行交互,并获取景点信息。

// 声明应用用到的命名空间
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Dynamic;
using System.Linq.Expressions;
using System.Net;
using System.IO;
using System.Diagnostics;
using PuppeteerSharp;
namespace Lenarn_Csharp
{
    class Program
    {
        /// <summary>
        /// 在无头浏览器中成功加载网页后,通过搜索本地旅游景点与网页进行交互
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public static async Task Main(string[] args)
        {
            var options = new LaunchOptions { Headless = true };
            Console.WriteLine("Downloading chromium");

            await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
            Console.WriteLine("Navigating to developers.google.com");

            using (var browser = await Puppeteer.LaunchAsync(options))
            using (var page = await browser.NewPageAsync())
            {
                // Create a new page and go to Bing Maps
                //Page page = await browser.NewPageAsync();
                await page.GoToAsync("https://www.bing.com/maps");
                //拍摄页面截图
                await page.ScreenshotAsync("D:\\test\\screenshot.png");
                // Search for a local tourist attraction on Bing Maps
                await page.WaitForSelectorAsync("input#maps_sb");
                await page.ScreenshotAsync("D:\\test\\screenshot1.png");
                //使用选择器获取元素并将其聚焦
                await page.FocusAsync("input#maps_sb");
                await page.ScreenshotAsync("D:\\test\\screenshot2.png");
                //Sends a keydown, keypress/input, and keyup event for each character in the text.
                await page.Keyboard.TypeAsync("Window of the World, shenzhen, guangdong, china");
                await page.ScreenshotAsync("D:\\test\\screenshot3.png");

                //使用选择器获取元素,如果需要,将其滚动到视图中,然后使用Puppetersharp.Page。用鼠标单击元素的中心。
                await page.ClickAsync(".searchIcon");
                await page.ScreenshotAsync("D:\\test\\screenshot4.png");
                DateTime dt1 = DateTime.Now;
                while ((DateTime.Now - dt1).TotalMilliseconds < 3000)
                {
                    continue;
                };
                //await page.WaitForNavigationAsync();
                await page.ScreenshotAsync("D:\\test\\screenshot5.png");
                var resultsSelector = "span.b_address";
                await page.WaitForSelectorAsync(resultsSelector);
                var links = await page.EvaluateFunctionAsync(@"(resultsSelector) => {
    const anchors = Array.from(document.querySelectorAll(resultsSelector));
    return anchors.map(anchor => {
      const title = anchor.textContent.split('|')[0].trim();
      return `${title} - ${anchor.href}`;
    });
}", resultsSelector);
                foreach (var link in links)
                {
                    Console.WriteLine(link);
                }
                Console.WriteLine("Press any key to continue...");
                Console.ReadLine();

            }
        }
    }
}
    
    
        

结果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

参考引用

Puppeteer Sharp - Examples
Puppeteer Sharp原理与使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值