WebView2 通過 PuppeteerSharp 實現爬取 王者 壁紙 (案例版)

来源:https://www.cnblogs.com/kesshei/archive/2022/08/10/16570947.html
-Advertisement-
Play Games

此案例是《.Net WebView2 項目,實現 嵌入 WEB 頁面 Chromium內核》文的續集。 主要是針對WebView2的一些微軟自己封裝的不熟悉的API,有一些人已經對 PuppeteerSharp很熟悉了,那麼,直接用 PuppeteerSharp的話,那就降低了學習成本,那還是很有必 ...


此案例是《.Net WebView2 項目,實現 嵌入 WEB 頁面 Chromium內核》文的續集。

主要是針對WebView2的一些微軟自己封裝的不熟悉的API,有一些人已經對 PuppeteerSharp很熟悉了,那麼,直接用 PuppeteerSharp的話,那就降低了學習成本,那還是很有必須要的。

之前自己也RPA獲取過聯盟的高清原畫,現在就獲取下王者的高清壁紙。

王者壁紙自動化獲取邏輯分析

其實它的邏輯很簡單, 就是王者的官網,打開後,在右下角就看到了皮膚頁面部分。

這個時候,點擊更多,就會打開全部英雄詳情的頁面。

這個時候,單點任意一個英雄,就會新開一個頁面,這個英雄自己的頁面,可以看到具體的皮膚信息了。

這裡可以看到有6個皮膚,那麼,到這裡我就可以獲取這6個皮膚作為高清王者的皮膚了。

那麼,讓程式自動化操作,並把這些信息處理保存好,就是我們要做到的事情。

新建一個WPF項目

新建一個 WPF 項目,要添加 Nuget 包

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

MainWindow.xaml

界面大致樣子和佈局

<DockPanel>
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" HorizontalAlignment="Right">
        <Label Name = "loginfo" Content="未採集"/>
        <Button Name="start" DockPanel.Dock="Right" Width="150" Content="開始採集" Click="start_Click"/>
    </StackPanel>
    <wpf:WebView2 Name = "webView2"/>
</DockPanel>

右上角一個提示信息,一個採集的按鈕,佈局很是簡單

如何啟用 PuppeteerSharp

其實都是基於谷歌的DevTools協議來的,所以,只要WebView2開啟了Debugging埠即可。

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

通過WebVeiw2的游覽器啟動參數 : --remote-debugging-port=6666 來開啟DevTools協議的支持。

PuppeteerSharpHelper

public class PuppeteerSharpHelper
{
    /// <summary>
    /// 獲取游覽器對象
    /// </summary>
    public static Task<Browser> GetBrowser(int port, int height, int width)
    {
        return Puppeteer.ConnectAsync(new ConnectOptions { DefaultViewport = new ViewPortOptions() { Height = height, Width = width }, BrowserWSEndpoint = WSEndpointResponse.GetWebSocketDebuggerUrl(port) });
    }
    internal class WSEndpointResponse
    {
        public string WebSocketDebuggerUrl { get; set; }
        public static string GetWebSocketDebuggerUrl(int port)
        {
            string data;
            using (var client = new HttpClient())
            {
                data = client.GetStringAsync($"http://127.0.0.1:{port}/json/version").Result;
            }
            return JsonConvert.DeserializeObject<WSEndpointResponse>(data).WebSocketDebuggerUrl;
        }
    }
}

所用到的王者實體信息

/// <summary>
/// 英雄的信息
/// </summary>
public class HeroInfo
{
    public string Name { get; set; }
    public string Url { get; set; }
    public string TargetUrl()
    {
        return $"https://pvp.qq.com/web201605/{Url}";
    }
    public List<HeroSkin> HeroSkins { get; set; }
}
/// <summary>
/// 英雄皮膚
/// </summary>
public class HeroSkin
{
    public HeroSkin(string name, string url)
    {
        this.Name = name;
        this.Url = "https:" + url;
    }
    public string Name { get; set; }
    public string Url { get; set; }
}

RPA的核心代碼

private async void start_Click(object sender, RoutedEventArgs e)
{
    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");

    await Currentpage.GoToAsync(herolistPath, WaitUntilNavigation.DOMContentLoaded);
    loginfo.Content = "開始獲取內容";
    var herolist = await Currentpage.EvaluateExpressionAsync<string>("document.querySelector('body > div.wrapper > div > div > div.herolist-box > div.herolist-content > ul').innerHTML");
    var heros = GetHeroInfos(herolist);
    loginfo.Content = $"獲取全部英雄信息共:{heros.Count}條";
    foreach (var item in heros)
    {
        await Currentpage.GoToAsync(item.TargetUrl(), WaitUntilNavigation.DOMContentLoaded);
        Thread.Sleep(100);
        var skins = await Currentpage.EvaluateExpressionAsync<string>("document.querySelector('body > div.wrapper > div.zk-con1.zk-con > div > div > div.pic-pf > ul').innerHTML");
        item.HeroSkins = GetHeroSkins(skins);
    }
    loginfo.Content = "開始下載資源";
    var count = 0;
    //開始執行下載
    foreach (var item in heros)
    {
        count++;
        loginfo.Content = $"資源一共:{heros.Count}條,正在下載第{count}條,還剩下:{heros.Count - count}";
        var HearoPath = System.IO.Path.Combine(ImagesPath, item.Name);
        if (!System.IO.Directory.Exists(HearoPath))
        {
            System.IO.Directory.CreateDirectory(HearoPath);
        }
        foreach (var skin in item.HeroSkins)
        {
            await WebHelper.DownloadFile(skin.Url, System.IO.Path.Combine(HearoPath, $"{skin.Name}.jpg"));
        }
    }
    loginfo.Content = "獲取完畢,等待查看!";
}

效果如下:

需要點擊獲取按鈕,就會執行自動化獲取操作,然後把獲取的內容存儲到當前項目bin目錄images目錄下。

下麵就是下載完後的效果。


整整齊齊,很完整,都是我喜歡的英雄和買不起的皮膚。


而且,獲取到的包含了皮膚的名稱

總結

基於WebView2,技術又深一層次的展開,一個好的技術,必定用到合適的場景上才是最合適的。

代碼地址

https://github.com/kesshei/WangZheRongYao.git

https://gitee.com/kesshei/WangZheRongYao.git

一鍵三連呦!,感謝大佬的支持,您的支持就是我的動力!

版權

藍創精英團隊(公眾號同名,CSDN 同名,CNBlogs 同名)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • “強引用、軟引用、弱引用、虛引用有什麼區別?” 這個問題難倒了很多資深Java工程師,不是因為這個問題本身有多難。 而是確實它是一個比較小眾的知識點。 大家好,我是Mic,一個工作了14年的Java程式員。 今天給大家分享一下這道面試題的標準回答。 文字版本我整理到了一個15W字的面試文檔裡面,大家 ...
  • 多商戶商城系統,也稱為B2B2C(BBC)平臺電商模式多商家商城系統。可以快速幫助企業搭建類似拼多多/京東/天貓/淘寶的綜合商城。 多商戶商城系統支持商家入駐加盟,同時滿足平臺自營、旗艦店等多種經營方式。平臺可以通過收取商家入駐費,訂單交易服務費,提現手續費,簡訊通道費等多手段方式,實現整體盈利。 ...
  • 在Spring Security中可以同時存在多個過濾器鏈,一個WebSecurityConfigurerAdapter的實例就可以配置一條過濾器鏈。 我們來看如下一個案例: @Configuration public class SecurityConfig { @Bean UserDetails ...
  • 2 併發容器線程安全應對之道 引言 在前面,我們學習了hashmap 大家都知道HashMap不是線程安全(put、刪除、修改、遞增、擴容都無鎖)的 所以在處理併發的時候會出現問題 接下來我們看下J.U.C包裡面提供的一個線程安全並且高效Map(ConcurrentHashMap) 看一下,他到底是 ...
  • 前言:Maui終於在昨天(2022年8月9日)推送出來了。今兒就迫不及待來把玩一下先。 A、我本地已有VS2022,不過版本比較老,此處選擇更新。工具 -> 獲取功能和更新裡面,可以獲取到新版本更新。 B、最新版本是17.3.0,我本地只有17.1.1,選擇 更新。 C、讓網路飛一會兒。 1、更新完 ...
  • 依賴註入容器之所以能夠提供應用程式所需的服務對象,是因為服務註冊為容器提供了創建服務對象的描述信息,而這個服務註冊的描述信息是被封裝在一個由ServiceDescriptor類型表示的對象中,該對象主要存儲在IServiceCollection類型的集合中,其中每個ServiceDescriptor ...
  • 老闆加薪!看我做的WPF Loading!!! 控制項名:RingLoading 作者:WPFDevelopersOrg 原文鏈接: https://github.com/WPFDevelopersOrg/WPFDevelopers 框架使用大於等於.NET40; Visual Studio 2022 ...
  • 基於.NetCore的積木化服務框架(Gitee地址),主要將常規解決方案進行進一步的抽象下沉形成相關基礎可選框架單元(在Framework 目錄),併在此基礎上實現常規系統模塊(在Modules 目錄),如用戶管理,許可權管理等。 當前項目,目的是為了提供一個思路,而不是模板。除了 Framewor ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...