首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

.NET 使用 mshtml 解析 HTML:WebClient + HTMLDocumentClass 實作

     編輯:ASP.NET 基礎

前言

在 .NET 中解析 HTML 文件,常見做法有 HtmlAgilityPack、AngleSharp 等第三方庫。若不想引入外部依賴,可使用 Windows 內建的 mshtml (Microsoft HTML Object Library),即 IE/MSHTML 解析引擎的 COM 包裝。本文示範如何透過 WebClient 下載網頁,再用 HTMLDocumentClass 解析標題、Body 文字等資訊。

準備工作

  1. 專案右鍵 → 加入參考 → COM → 搜尋 Microsoft HTML Object Library → 勾選 mshtml。
  2. 引用後會在 bin 產生 Microsoft.mshtml.dll (Interop 組件)。
  3. 若部署至無 IE 的 Server Core 環境,mshtml 可能無法運作;建議改用 HtmlAgilityPack。

核心程式碼


using System;
using System.Net;
using System.Text;
using mshtml; // 命名空間

class HtmlParserDemo
{
    static void Main()
    {
        string url = "https://www.jb51.net/web/73969.html";

        // 1. 下載 HTML 內容
        using (var wc = new WebClient())
        {
            wc.Encoding = Encoding.UTF8; // 關鍵:指定編碼,避免亂碼
            string html = wc.DownloadString(url);

            // 2. 建立 MSHTML 文件物件
            var doc = new HTMLDocumentClass();
            
            // 3. 關鍵設定:designMode = "on" 防止腳本執行、圖片下載、跳轉等副作用
            doc.designMode = "on";
            
            // 4. 寫入 HTML 字串
            // IHTMLDocument2_write 接受 object[],需用反射或 dynamic 呼叫
            // 簡易寫法:dynamic doc2 = doc; doc2.write(html);
            dynamic doc2 = doc;
            doc2.write(html);
            
            // 5. 關閉寫入流
            doc2.close();

            // 6. 擷取資訊
            Console.WriteLine("Title: " + doc.title);
            Console.WriteLine("Body Text (前500字): " + doc.body?.innerText?.Substring(0, Math.Min(500, doc.body.innerText.Length)));
            
            // 7. 進階:查詢特定元素
            // var links = doc.getElementsByTagName("a");
            // foreach (IHTMLElement link in links) Console.WriteLine(link.getAttribute("href"));
        }

        Console.ReadKey();
    }
}

關鍵 API 說明

成員 型別/介面 用途
HTMLDocumentClass Class MSHTML 文件實體,實作 IHTMLDocument2、IHTMLDocument3 等介面
designMode string "on" = 設計模式,禁用腳本執行、資源下載;"off" = 瀏覽模式
write(html) method 將 HTML 字串解析載入文件
close() method 結束寫入,觸發 DOM 完成事件
title string 文件 <title> 內容
body IHTMLElement <body> 元素,含 innerText、innerHTML
getElementsByTagName method 依標籤名稱取得元素集合
getElementById method 依 ID 取得單一元素

進階:使用 IHTMLDocument3 的 createDocumentFromUrl (非同步載入)


// 此方法會自動下載並解析,但較難控制編碼與逾時,不建議生產環境使用
var doc3 = (IHTMLDocument3)new HTMLDocumentClass();
doc3.createDocumentFromUrl(url, null);
// 需等待 readyState == "complete",可用事件或輪詢

編碼處理最佳實務

  1. WebClient.Encoding = Encoding.UTF8:強制以 UTF-8 解碼位元組。
  2. 若網頁宣告非 UTF-8(如 Big5),需先 DownloadData 取得 byte[],再用 Encoding.GetEncoding("big5").GetString(bytes)。
  3. MSHTML 內部以 Unicode 儲存,寫入時已轉換完成。

替代方案比較(強烈建議)

方案 優點 缺點 推薦度
HtmlAgilityPack 純 .NET、無 COM 依賴、支援 XPath/LINQ、容錯率高、NuGet 即裝即用 需額外套件 ⭐⭐⭐⭐⭐ (首選)
AngleSharp 現代標準、支援 CSS Selector、DOM 完整、非同步、.NET Standard 效能略低於 HAP ⭐⭐⭐⭐
mshtml (本文) 零第三方套件、Windows 內建、IE 相容性最好 需註冊 COM、部署麻煩、非執行緒安全、Server Core 不支援、效能差 ⭐⭐ (特定舊專案維護)
System.Web.HttpUtility.HtmlDecode 僅解碼 HTML 實體,非解析器 無 DOM 操作 ⭐

HtmlAgilityPack 快速上手(推薦替代)


// NuGet: Install-Package HtmlAgilityPack
using HtmlAgilityPack;

var web = new HtmlWeb();
var doc = web.Load(url); // 自動處理編碼、重導向、Cookie

Console.WriteLine(doc.DocumentNode.SelectSingleNode("//title").InnerText);
Console.WriteLine(doc.DocumentNode.SelectSingleNode("//body").InnerText.Substring(0, 500));

// XPath 查詢所有連結
foreach (var link in doc.DocumentNode.SelectNodes("//a[@href]"))
    Console.WriteLine(link.GetAttributeValue("href", ""));

常見問題排除

  1. 「找不到 mshtml」/ 型別載入失敗:確認專案參考 → COM → Microsoft HTML Object Library 已勾選,且 Embed Interop Types = False (預設)。
  2. 中文亂碼:檢查 WebClient.Encoding 是否正確設定;若網頁無 charset meta,嘗試自動偵測 (HtmlAgilityPack 內建)。
  3. 腳本錯誤彈窗/卡住:務必設定 doc.designMode = "on" 在 write 之前。
  4. 存取 body.innerText 為 null:HTML 可能無 <body> 標籤,需先檢查 doc.body != null。
  5. 多執行緒呼叫:MSHTML 為 STA COM 物件,不可跨執行緒共用 HTMLDocumentClass 實例,每個執行緒需自行建立。

總結

  • mshtml 提供無第三方依賴的 HTML 解析能力,適合極度受限環境、舊專案維護。
  • 核心流程:WebClient.DownloadString → new HTMLDocumentClass() → designMode="on" → write(html) → close() → 讀取 title/body.innerText。
  • 新專案請直接使用 HtmlAgilityPack 或 AngleSharp,開發效能、穩定性、部署便利性全面優於 mshtml。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved