[C#]Google Chrome 書簽導出並生成 MHTML 文件

来源:https://www.cnblogs.com/myzony/archive/2018/03/02/8494137.html
-Advertisement-
Play Games

目的 因為某些原因需要將存放在 Google Chrome 內的書簽導出到本地,所幸 Google Chrome 提供了導出書簽的功能。 分析 首先在 Google Chrome 瀏覽器當中輸入 來到書簽管理頁面,找到最右側的三個點,選擇導出書簽,導出的文件是一個 HTML 文件,裡面包含了所有書簽 ...


目的

因為某些原因需要將存放在 Google Chrome 內的書簽導出到本地,所幸 Google Chrome 提供了導出書簽的功能。

分析

首先在 Google Chrome 瀏覽器當中輸入 chrome://bookmarks 來到書簽管理頁面,找到最右側的三個點,選擇導出書簽,導出的文件是一個 HTML 文件,裡面包含了所有書簽的層級結構等信息。

使用 Notepad++ 打開該文件之後可以看到裡面的內容如下:
http://blog.myzony.com/files/GoogleChromeExport-1.png

粗略一看貌似沒什麼問題,其實在裡面的 <DT><P> 都缺少了閉合標簽,所以在解析的時候需要將其去除掉。去除掉之後的 HTML 文件結構大概像這樣:

<DL>
    <H3>文件夾標題</H3>
    <DL>
        <H3>子文件夾標題</H3>
        <A HREF="書簽地址">子文件夾書簽1</A>
        <A HREF="書簽地址">子文件夾書簽2</A>
    </DL>
    <A HREF="書簽地址">書簽1</A>
    <A HREF="書簽地址">書簽2</A>
</DL>

可以很明顯看到這裡是有一個層級關係的,所以我們可以通過遞歸來生成一個樹形模型,生成之後,再遍歷這個模型來根據這個樹形結構來創建 MHTML 文件,並且進行歸類。

實現

操作 HTML 文件在 .Net 下有一個很方便的第三方庫,名字叫做 HtmlAgilityPack,通過這個庫我們可以很方便地操作 HTML 文檔,就跟 DOM 一樣方便,而且它支持 XPath 選取。

項目地址:http://html-agility-pack.net/
GitHub 地址:https://github.com/zzzprojects/html-agility-pack
Nuget 地址:https://www.nuget.org/packages/HtmlAgilityPack/

通過 Nuget 安裝該包到項目當中,引入 HtmlAgilityPack 命名空間,就可以開始編寫代碼了。

1.編寫 HtmlResolver 解析器

建立一個 HtmlResolver 類,該類用於解析 Chrome 導出的書簽:

public class HtmlResolver
{
    private HtmlDocument _htmlDocument = new HtmlDocument();

    /// <summary>
    /// 初始化 HTML 解析器
    /// </summary>
    /// <param name="htmlPath">Google Chrome 導出的書簽 HTML 路徑</param>
    public HtmlResolver(string htmlPath)
    {
        using (FileStream htmlFileStream = File.Open(htmlPath, FileMode.Open))
        {
            using (StreamReader htmlReader = new StreamReader(htmlFileStream))
            {
                // 移除干擾標簽
                string htmlStr = htmlReader.ReadToEnd();
                htmlStr = htmlStr.Replace(@"<DT>", string.Empty).Replace(@"<p>", string.Empty);

                // 載入 HTML
                _htmlDocument.LoadHtml(htmlStr);
            }
        }
    }
}

在對象初始化的時候要求提供 Google Chrome 導出的書簽 HTML 文件路徑,並且讀入 HTML 文件數據的時候移除掉之前所說的 <DT><P> 標簽,方便後面 HtmlAgilityPack 進行解析,移除之後,HtmlDocument 通過 HTML String 初始化。

2.創建書簽模型

當我們遞歸完成之後需要將數據存儲在書簽模型當中,方便後面生成 MHTML 文件的時候使用。

/// <summary>
/// 書簽模型
/// </summary>
public class BookMarkModel
{
    /// <summary>
    /// 初始化書簽模型
    /// </summary>
    /// <param name="name">書簽名稱</param>
    /// <param name="path">書簽路徑</param>
    /// <param name="url">綁定的 URL</param>
    /// <param name="childNodes">子節點集合</param>
    public BookMarkModel(string name, string path, string url = null, List<BookMarkModel> childNodes = null)
    {
        Name = name;
        Url = url;
        ChildNodes = childNodes;
        Path = path;
    }

    /// <summary>
    /// 書簽名稱
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 綁定的 URL
    /// </summary>
    public string Url { get; set; }
    /// <summary>
    /// 書簽路徑
    /// </summary>
    public string Path { get; set; }
    /// <summary>
    /// 子節點集合,如果沒有則為 NULL
    /// </summary>
    public List<BookMarkModel> ChildNodes { get; set; }
}

該模型是一個典型的樹形結構,之後我們就開始遞歸生成書簽模型了。

3.遞歸生成樹形模型

遞歸演算法自己一直不太會寫,寫好這一個遞歸方法基本都花費了半天的時間 :P,後面打算惡補數學和演算法這塊了。下麵先上代碼再解釋原理:

/// <summary>
/// 遞歸生成書簽模型
/// </summary>
/// <param name="node">父級節點</param>
/// <param name="parentPath">父級節點 Path</param>
private List<BookMarkModel> RecursionGenerate(HtmlNode node, string parentPath)
{
    List<BookMarkModel> bookMarkModels = new List<BookMarkModel>();

    // 獲取所有文件夾標題與其下屬節點,以便遞歸查詢其子節點
    var bookMarkFolderTitles = node.SelectNodes("h3")?.Cast<HtmlNode>().ToList();
    var bookMarkFolder = node.SelectNodes("dl")?.Cast<HtmlNode>().ToList();

    var htmlBookMarks = node.SelectNodes("a");

    // 如果文件夾不存在則直接將所有具體書簽返回
    if (bookMarkFolderTitles == null || bookMarkFolder == null)
    {
        return GenerateBookMarkModels(htmlBookMarks, parentPath);
    }

    // 遞歸構建書簽模型
    for (int i = 0; i < bookMarkFolderTitles.Count; i++)
    {
        BookMarkModel bookMark = new BookMarkModel(bookMarkFolderTitles[i].InnerText, $@"{parentPath}\{bookMarkFolderTitles[i].InnerText}.mhtml");

        bookMark.ChildNodes = RecursionGenerate(bookMarkFolder[i], bookMark.Path);
        List<BookMarkModel> bookmarks = GenerateBookMarkModels(htmlBookMarks, parentPath);
        if (bookmarks != null) bookMark.ChildNodes?.AddRange(bookmarks);

        bookMarkModels.Add(bookMark);
    }

    return bookMarkModels;
}

首先說說 RecursionGenerate(HtmlNode node,string parentPath) 方法,這個方法接收一個節點參數,這個節點就是需要遍歷的節點,而 parentPath 則是用於生成路徑的,在每次構建書簽模型的時候都會根據父級路徑來生成新的路徑。

如果要獲取某個節點下麵的子節點,肯定要拿到該節點下屬的所有節點,可以參考上面的大概結構,一般一個書簽文件夾下麵都會有一個或多個子文件夾,也有可能會有部分書簽與這些子文件夾同級。

所以,我們先提取出當前節點的文件夾名稱,也就是 <H3> 標簽裡面的內容,然後只要有一個 <H3> 標簽,那他肯定有一個對應的 <DL> 標簽表示包裹著它的子節點內容。如果某個節點它的內部沒有子文件夾的話,那直接抓取其內部的具體書簽,並返回出來。

如果某個節點擁有子文件夾的話,遍歷其內部,並且再次調用 RecursionGenerate 方法,將其內部節點添加到這個節點的 Childern 當中。

註意,這裡在迴圈內部還再次進行了獲取具體書簽的操作,因為有的時候某個節點內部也是擁有具體書簽項的,所以這裡才會有 List<T>.AddRange(IEnumerable<T> list) 操作。

具體書簽生成:

/// <summary>
/// 將 A 標簽的集合轉換為 BookMarkModel 集合
/// </summary>
/// <param name="nodes">A 標簽節點集合</param>
/// <returns>轉換完成的 Node 集合</returns>
private List<BookMarkModel> GenerateBookMarkModels(HtmlNodeCollection nodes, string parentPath)
{
    if (nodes == null) return null;

    List<BookMarkModel> bookmarks = new List<BookMarkModel>();

    foreach (var node in nodes)
    {
        bookmarks.Add(new BookMarkModel(node.InnerText, $@"{parentPath}\{node.InnerText}.mhtml", node.Attributes["href"].Value));
    }

    return bookmarks;
}

具體書簽的生成就很簡單了,直接構建即可,這裡會在其末尾添加 .mhtml 尾碼。

4.根據生成的書簽模型來產生 MHTML 文件

這裡可以參考以下實現:
https://code.msdn.microsoft.com/windowsdesktop/Creating-a-MHTML-MIME-HTML-61cf5dd1

目前程式還沒有實現這一個功能,因為使用 CDO 的方法不太方便,而且生成的 MHT 文件樣式丟失嚴重,並不像 Google Chrome 保存的 mht 文件那樣完整。

後續再來填坑。

結尾

項目地址:http://git.myzony.com/Zony/GoogleBookmarkExportTool


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

-Advertisement-
Play Games
更多相關文章
  • 一、IO 概述 1、IO 概念 IO:I 代表 Input 輸入;O 代表 Output 輸出。 Java 中 IO 是以流為基礎進行輸入輸出,所有的數據被串列化(保存)寫入輸出流,或者從輸入流讀入。 註:數據串列化指把對象的狀態以特定的形式(比如 byte[])保存到流,通過流的方式寫入。 2、I ...
  • import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.... ...
  • 最近在eclipse中,使用svn導入svn上的一個maven項目,但是導入後類的包並沒有以源碼包的方式顯示,而是以普通文件包的方式顯示出來,在對類進行F3等操作時就報錯:“the resource is not on the build path of a java project”。 這種情況的 ...
  • Maven是優秀的Java項目對象模型解決方案,意為知識的積累(意地緒文),Maven可以方便的解決Java項目包依賴問題,通過配置pom.xml引入依賴,並自動引入其他依賴。 操作系統版本:windows 7 Eclipse版本:Oxygen.1a(4.7.1a) Maven版本:3.5.2 JD ...
  • if 語句結構 if 判斷條件: 要執行的代碼 判斷條件:一般為關係表達式或者bool類型的值 執行過程:程式運行到if處,首先判斷if所帶的條件,如果條件成立,就返回True,則執行if所帶的代碼;如果條件不成立,就返回值是False, 跳過if語句繼續向下執行。 示例1: 在控制台應用程式中輸入 ...
  • 簡介 IMapControl介面最重要的是包含IMap屬性,還提供另外的屬性用於:管理一般的外觀顯示,管理圖層,載入地圖文檔以及跟蹤在界面上顯示的圖形。 小知識點:一般一個介面的最新實現是 Default ,如果又多個實現,是通過數字區分,數字越大,其版本也越新。 屬性介紹 1. IActiveVi ...
  • 目錄 xBIM WeXplorer 簡要介紹 xBIM WeXplorer xViewer 基本應用 xBIM WeXplorer xViewer 瀏覽器檢查 xBIM WeXplorer xViewer的導航,相機、剖切、隱藏 等操作 xBIM WeXplorer 設置模型顏色 xBIM 綜合使用 ...
  • https://www.cnblogs.com/xishuai/p/asp-net-5-owin-katana.html http://wiki.jikexueyuan.com/project/think-in-asp-net-mvc/chapter-eight.html http://wiki.j ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...