一 本系列隨筆概覽及產生的背景html
本系列開篇受到你們的熱烈歡迎,這對博主是莫大的鼓勵,此爲本系列第三篇,但願你們繼續支持,爲我繼續寫做提供動力。git
本身開發的豆約翰博客備份專家軟件工具問世3年多以來,深受廣大博客寫做和閱讀愛好者的喜好。同時也不乏一些技術愛好者諮詢我,這個軟件裏面各類實用的功能是如何實現的。github
該軟件使用.NET技術開發,爲回饋社區,現將該軟件中用到的核心技術,開闢一個專欄,寫一個系列文章,以饗廣大技術愛好者。數據庫
本系列文章除了講解網絡採編發用到的各類重要技術以外,也提供了很多問題的解決思路和界面開發的編程經驗,很是適合.NET開發的初級,中級讀者,但願你們多多支持。編程
不少初學者常有此類困惑,「爲何我書也看了,C#相關的各個方面的知識都有所瞭解,但就是無法寫出一個像樣的應用呢?」windows
這其實仍是沒有學會綜合運用所學知識,鍛煉出編程思惟,創建起學習興趣,我想該系列文章也許會幫到您,希望如此。網絡
開發環境:VS2008框架
本節源碼位置:https://github.com/songboriceboy/GetWebAllPics工具
源碼下載辦法:安裝SVN客戶端(本文最後提供下載地址),而後checkout如下的地址:https://github.com/songboriceboy/GetWebAllPics.gitpost
系列文章提綱以下:
二 第三節主要內容簡介(如何使用C#語言下載博文中的所有圖片到本地並能夠離線瀏覽)
網頁的抓取主要分爲3步:
1.經過分頁連接抓取到所有文章連接集合(第一節內容)
2.經過每個文章連接獲取到文章的標題及正文(第二節內容)
3.從文章正文中解析出所有圖片連接,並將文章的所有圖片下載到本地(本節內容)
這3步有了,以後你就想怎麼折騰就怎麼折騰了,各類加工處理,生成pdf,chm,靜態站點,遠程發佈到其餘站點等等。
如何使用C#語言下載博文中的所有圖片到本地並能夠離線瀏覽的解決方案演示demo以下圖所示:可執行文件下載
點擊下載正文所有圖片按鈕後,會在可執行程序所在目錄生成一個文件夾(文字爲該網頁的標題),文件夾中包含一個html文件(網頁正文)以及網頁正文中的所有圖片。該html文件對最初正文html文件進行了處理,其中的圖片連接均修改爲了本地圖片文件。
三 基本原理
下載博文中的所有圖片能夠分解成3步:
1.下載網頁正文,找出其中的所有圖片連接地址;
2.對於每個圖片連接地址,下載該圖片到本地(起一個文件名),同時替換原來的圖片地址爲咱們剛剛起的文件名;
3.第二步所有圖片下載完成後,將全部圖片連接替換後的網頁正文保存爲一個新的html文件(index.html)。
接下來咱們就一步一步來看一下如何作:
1.下載網頁正文,找出其中的所有圖片連接地址;
如何下載網頁正文請參考第二節內容,下面我們看一下如何來獲取網頁正文中的所有圖片連接:
private void GetSrcLinks() { HtmlNodeCollection atts = m_Doc.DocumentNode.SelectNodes("//*[@src]"); if (Equals(atts, null)) { return; } Links = atts. SelectMany(n => new[] { ParseLink(n, "src"), }). Distinct(). ToArray(); }
經過HtmlAgilityPack中的HtmlDocument類找出所有src屬性的節點,再經過linq提取出其中的網頁地址。
2.對於每個圖片連接地址,下載該圖片到本地,以下代碼所示:
DocumentWithLinks links = htmlDoc.GetSrcLinks(); int i = 1; string baseUrl = new Uri(strLink).GetLeftPart(UriPartial.Authority); foreach (string strPicLink in links.Links) { if (string.IsNullOrEmpty(strPicLink)) { continue; } try { string strExtension = System.IO.Path.GetExtension(strPicLink); if (strExtension == ".js" || strExtension == ".swf") continue; if (strExtension == "") { strExtension = ".jpg"; } string normalizedPicLink = GetNormalizedLink(baseUrl, strPicLink); strNewPage = DownLoadPicInternal(wc, strNewPage, strPageTitle, strPicLink, normalizedPicLink, strExtension, ref i); } catch (Exception ex) { } //end try }
其中 DownLoadPicInternal的實現代碼以下:
protected string DownLoadPicInternal(WebClient wc, string strNewPage, string strPageTitle, string strPicLink , string strTureLink, string strExtension, ref int i) { strPageTitle = strPageTitle.Replace("\\", "").Replace("/", "").Replace(":", "").Replace("*", "").Replace("?", "") .Replace("\"", "").Replace("<", "").Replace(">", "").Replace("|", ""); strPageTitle = Regex.Replace(strPageTitle, @"[|•/\;.':*?<>-]", "").ToString(); strPageTitle = Regex.Replace(strPageTitle, "[\"]", "").ToString(); strPageTitle = Regex.Replace(strPageTitle, @"\s", ""); if (!Directory.Exists(Application.StartupPath + "\\" + strPageTitle))//判斷是否存在 { Directory.CreateDirectory(Application.StartupPath + "\\" + strPageTitle);//建立新路徑 } int[] nArrayOffset = new int[2]; nArrayOffset = m_bf.getOffset(strPicLink); strNewPage = strNewPage.Replace(strPicLink, nArrayOffset[0].ToString() + nArrayOffset[1].ToString() + strExtension); string strSavedPicPath = Path.Combine(strPageTitle, nArrayOffset[0].ToString() + nArrayOffset[1].ToString() + strExtension); PrintLog(" 開始下載文章 [" + strPageTitle + "] 的第" + i.ToString() + "張圖片\n"); strTureLink = HttpUtility.UrlDecode(strTureLink); wc.DownloadFile(strTureLink, Application.StartupPath + "\\" + strSavedPicPath); PrintLog(" 下載完成文章 [" + strPageTitle + "] 的第" + i.ToString() + "張圖片\n"); System.Threading.Thread.Sleep(300); i++; return strNewPage; }
其中粉色代碼部分m_bf變量是BloomFilter類型的一個對象,BloomFilter是一個網頁去重的強大工具,這裏是爲了將圖片連接轉化爲一個獨一無二的文件名。
strNewPage = strNewPage.Replace(strPicLink, nArrayOffset[0].ToString() + nArrayOffset[1].ToString() + strExtension);
此行代碼是用新的圖片文件名替換原網頁中的圖片連接。其餘部分的代碼以前章節均有解釋,請自行參考。
3.第二步所有圖片下載完成後,將全部圖片連接替換後的網頁正文保存爲一個新的html文件(index.html),主要代碼以下:
strPageTitle = strPageTitle.Replace("\\", "").Replace("/", "").Replace(":", "").Replace("*", "").Replace("?", "") .Replace("\"", "").Replace("<", "").Replace(">", "").Replace("|", ""); strPageTitle = Regex.Replace(strPageTitle, @"[|•/\;.':*?<>-]", "").ToString(); strPageTitle = Regex.Replace(strPageTitle, "[\"]", "").ToString(); strPageTitle = Regex.Replace(strPageTitle, @"\s", ""); File.WriteAllText(Path.Combine(strPageTitle, "index.html"), strNewPage, Encoding.UTF8);
上面的一堆替換是由於windows對文件夾名有要求---不能包含一些特殊字符,這裏咱們經過正則替換去掉這些特殊字符。
到此爲止,咱們就實現了將任意網頁中的正文中的圖片下載到本地的功能,並同時修改了原來網頁正文中的圖片連接,以達到能夠離線瀏覽的目的。
之後的生成pdf,chm均以此爲基礎,這一節是重中之重,有興趣的同窗能夠擴展我提供的代碼,將它改形成某個站點的圖片採集器應該也是一件簡單的事情。
四 下節預告
使用C#語言如何將html網頁轉換成pdf(html2pdf)。