原本的預定是製作一個 XML的讀寫檔功能,目的是為了能夠紀錄要監控的對話視窗,但中間插入了一個想法是先把對話群組列出來,這樣到時候在設定畫面的時候就可以比較方便的做新增。
而在製作功能時遇到了一些關於 WebView 的問題,在以前的版本 C# 有內建 WebBrowser 的功能,但在目前的版本則是要自己裝套件,而我使用的是 Microsoft.Web.WebView2.Core 的版本核心。
但這個核心實際使用起來其實提供的東西不多(微軟 ...),而我的目的只是單純的想要 parse html 而已,在以前的 WebBrowser 記得就有內建 DOM 的功能庫可以使用,但在 WebView2 中卻好像沒有這個東西,也只能另尋他法
單就這個問題卡了大約一兩天,後來大概找了一下 Google,有找到別人提供的一些方法,其中一個是使用 HtmlAgilityPack 這個套件,可以透過 NuGet 下載安裝,所以就以這個當工具來試試。
他的使用方式不算複雜,網站裡面也都有說明。
最主要先使用到 WebView2 的 ExecuteScriptAsync 功能,把整個網站的 Body 內容取出來
var htmlCode = await browser.CoreWebView2.ExecuteScriptAsync("document.body.innerHTML");
但這邊有遇到一個問題,正常來說取得的結果是正確的標籤,但不曉得為什麼左 tag 會拿到 \u003C,所以內容會變成 \u003Cdiv>,隨意找了一下發現用 Unescape 就能處理。
htmlCode = Regex.Unescape(htmlCode); htmlCode = htmlCode.Remove(0, 1); htmlCode = htmlCode.Remove(htmlCode.Length - 1, 1);
接著,就可以使用 HtmlAgilityPack 中的 HtmlDocument 將整個 Html 包進來,這時候會變成類似 XmlNode 的物件,最後再使用 SelectNode 等方法就可以開始處理整段需求
透過這個方式後來有把對話的群組名稱全都抓到了,但 Skype 的網頁版畫面的元素並不是有指定的命名或者 id ,大多數爬網頁其實也會遇到同樣的問題,只要網頁結構改變就會抓不到需要改版,所以針對這問題就不著墨處理了
新加入的程式片段大概如下
var htmlCode = await browser.CoreWebView2.ExecuteScriptAsync("document.body.innerHTML"); if (htmlCode == null) { addInfoMessage("Get Html Code Error"); return; } htmlCode = Regex.Unescape(htmlCode); htmlCode = htmlCode.Remove(0, 1); htmlCode = htmlCode.Remove(htmlCode.Length - 1, 1); HtmlAgilityPack.HtmlDocument htmlDocument = new(); htmlDocument.LoadHtml(htmlCode); HtmlNodeCollection listitemNodes = htmlDocument.DocumentNode.SelectNodes("//div[@role=\"listitem\"]"); if (listitemNodes != null) { foreach (var node in listitemNodes) { try { HtmlNode picNode = node.ChildNodes[0].ChildNodes[0].ChildNodes[0]; if (!picNode.Attributes.Contains("title") || String.IsNullOrEmpty(picNode.Attributes["title"].Value)) { HtmlNode nameNode = node.ChildNodes[0].ChildNodes[0].ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0]; if (nameNode.Attributes.Contains("data-text-as-pseudo-element")) { string chatName = nameNode.Attributes["data-text-as-pseudo-element"].Value; if (!String.IsNullOrEmpty(chatName)) { chatList.Add(chatName); } } } else { string groupName = picNode.GetAttributeValue("title", ""); if (!String.IsNullOrEmpty(groupName)) { groupList.Add(groupName); } } } } }
最後附上努力更新的 Github
沒有留言:
張貼留言