• WebView2 通过 PuppeteerSharp 实现爬取 王者 壁纸 (案例版)


    王者壁纸自动化获取逻辑分析

    其实它的逻辑很简单, 就是王者的官网,打开后,在右下角就看到了皮肤页面部分。

    这个时候,点击更多,就会打开全部英雄详情的页面。

    这个时候,单点任意一个英雄,就会新开一个页面,这个英雄自己的页面,可以看到具体的皮肤信息了。

    这里可以看到有6个皮肤,那么,到这里我就可以获取这6个皮肤作为高清王者的皮肤了。

    那么,让程序自动化操作,并把这些信息处理保存好,就是我们要做到的事情。

    新建一个WPF项目

    新建一个 WPF 项目,要添加 Nuget

    1. Install-Package Microsoft.Web.WebView2 -Version 1.0.1293.44
    2. Install-Package PuppeteerSharp -Version 7.1.0
    3. Install-Package HtmlAgilityPack -Version 1.11.43

    MainWindow.xaml

    界面大致样子和布局

    1. <DockPanel>
    2. <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" HorizontalAlignment="Right">
    3. <Label Name = "loginfo" Content="未采集"/>
    4. <Button Name="start" DockPanel.Dock="Right" Width="150" Content="开始采集" Click="start_Click"/>
    5. </StackPanel>
    6. <wpf:WebView2 Name = "webView2"/>
    7. </DockPanel>

    右上角一个提示信息,一个采集的按钮,布局很是简单

    如何启用 PuppeteerSharp

    其实都是基于谷歌的DevTools协议来的,所以,只要WebView2开启了Debugging端口即可。

    1. var result = await CoreWebView2Environment.CreateAsync(null, System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "cache"),
    2. new CoreWebView2EnvironmentOptions($"--remote-debugging-port={Port}"));
    3. await webView2.EnsureCoreWebView2Async(result);

    通过WebVeiw2的游览器启动参数 : --remote-debugging-port=6666 来开启DevTools协议的支持。

    PuppeteerSharpHelper

    1. public class PuppeteerSharpHelper
    2. {
    3. /// <summary>
    4. /// 获取游览器对象
    5. /// </summary>
    6. public static Task<Browser> GetBrowser(int port, int height, int width)
    7. {
    8. return Puppeteer.ConnectAsync(new ConnectOptions { DefaultViewport = new ViewPortOptions() { Height = height, Width = width }, BrowserWSEndpoint = WSEndpointResponse.GetWebSocketDebuggerUrl(port) });
    9. }
    10. internal class WSEndpointResponse
    11. {
    12. public string WebSocketDebuggerUrl { get; set; }
    13. public static string GetWebSocketDebuggerUrl(int port)
    14. {
    15. string data;
    16. using (var client = new HttpClient())
    17. {
    18. data = client.GetStringAsync($"http://127.0.0.1:{port}/json/version").Result;
    19. }
    20. return JsonConvert.DeserializeObject<WSEndpointResponse>(data).WebSocketDebuggerUrl;
    21. }
    22. }
    23. }

    所用到的王者实体信息

    1. /// <summary>
    2. /// 英雄的信息
    3. /// </summary>
    4. public class HeroInfo
    5. {
    6. public string Name { get; set; }
    7. public string Url { get; set; }
    8. public string TargetUrl()
    9. {
    10. return $"https://pvp.qq.com/web201605/{Url}";
    11. }
    12. public List<HeroSkin> HeroSkins { get; set; }
    13. }
    14. /// <summary>
    15. /// 英雄皮肤
    16. /// </summary>
    17. public class HeroSkin
    18. {
    19. public HeroSkin(string name, string url)
    20. {
    21. this.Name = name;
    22. this.Url = "https:" + url;
    23. }
    24. public string Name { get; set; }
    25. public string Url { get; set; }
    26. }

    RPA的核心代码

    1. private async void start_Click(object sender, RoutedEventArgs e)
    2. {
    3. var herolistPath = await Currentpage.EvaluateExpressionAsync<string>("document.querySelector('body > div.wrapper > div.main > div:nth-child(3) > div.skin_center.fl > div.item_header > a').href");
    4. await Currentpage.GoToAsync(herolistPath, WaitUntilNavigation.DOMContentLoaded);
    5. loginfo.Content = "开始获取内容";
    6. var herolist = await Currentpage.EvaluateExpressionAsync<string>("document.querySelector('body > div.wrapper > div > div > div.herolist-box > div.herolist-content > ul').innerHTML");
    7. var heros = GetHeroInfos(herolist);
    8. loginfo.Content = $"获取全部英雄信息共:{heros.Count}条";
    9. foreach (var item in heros)
    10. {
    11. await Currentpage.GoToAsync(item.TargetUrl(), WaitUntilNavigation.DOMContentLoaded);
    12. Thread.Sleep(100);
    13. var skins = await Currentpage.EvaluateExpressionAsync<string>("document.querySelector('body > div.wrapper > div.zk-con1.zk-con > div > div > div.pic-pf > ul').innerHTML");
    14. item.HeroSkins = GetHeroSkins(skins);
    15. }
    16. loginfo.Content = "开始下载资源";
    17. var count = 0;
    18. //开始执行下载
    19. foreach (var item in heros)
    20. {
    21. count++;
    22. loginfo.Content = $"资源一共:{heros.Count}条,正在下载第{count}条,还剩下:{heros.Count - count}";
    23. var HearoPath = System.IO.Path.Combine(ImagesPath, item.Name);
    24. if (!System.IO.Directory.Exists(HearoPath))
    25. {
    26. System.IO.Directory.CreateDirectory(HearoPath);
    27. }
    28. foreach (var skin in item.HeroSkins)
    29. {
    30. await WebHelper.DownloadFile(skin.Url, System.IO.Path.Combine(HearoPath, $"{skin.Name}.jpg"));
    31. }
    32. }
    33. loginfo.Content = "获取完毕,等待查看!";
    34. }

    效果如下:

    需要点击获取按钮,就会执行自动化获取操作,然后把获取的内容存储到当前项目bin目录images目录下。

    下面就是下载完后的效果。


    整整齐齐,很完整,都是我喜欢的英雄和买不起的皮肤。


    而且,获取到的包含了皮肤的名称

    总结

    基于WebView2,技术又深一层次的展开,一个好的技术,必定用到合适的场景上才是最合适的。

  • 相关阅读:
    MySQL-备份+日志:介质故障与数据库恢复
    QChart柱状图
    两台电脑连接时,A电脑可以ping通B电脑,而B电脑pingA电脑时出现超时问题,解决:
    【Java集合】HashMap系列(五)——HashMap在JDK1.7和JDK1.8比较总结及常见面试题
    细品spring设计,可扩展性编程Aware接口,Adapter类
    【博客547】keepalived实现vip的原理剖析
    Linux环境下MySQL的数据目录
    前端构建效率优化之路
    js加密进阶与搭建Node服务
    技术分享 | 接口自动化测试如何进行认证?
  • 原文地址:https://blog.csdn.net/sinat_40572875/article/details/128090527