C#實現圖標批量下載

来源:http://www.cnblogs.com/liweis/archive/2016/04/02/5344528.html
-Advertisement-
Play Games

本文略微有些長,花了好幾晚時間編輯修改,若在措辭排版上有問題,請諒解。本文共分為四篇,下麵是主要內容,也是軟體開發基本流程。 階段 描述 需求分析 主要描述實現本程式的目的及對需求進行分析,即為什麼要花時間來編寫,需要哪些功能等; 方案設計 根據現有的需求,設計出一個可行的方案(即使可能還存在某些問 ...


本文略微有些長,花了好幾晚時間編輯修改,若在措辭排版上有問題,請諒解。本文共分為四篇,下麵是主要內容,也是軟體開發基本流程。

階段

描述

需求分析

主要描述實現本程式的目的及對需求進行分析,即為什麼要花時間來編寫,需要哪些功能等;

方案設計

根據現有的需求,設計出一個可行的方案(即使可能還存在某些問題),用戶需要輸入什麼,程式需要處理什麼,資料庫、功能、界面的設計等;

編程實現

通過.NET編程實現圖標批量下載的功能,重點分析其中遇到的問題及解決的方法。

成果展示

展示分享實現的工具及成果,小結經驗。

 

一、需求分析

在平時的程式開發中,為了快速搭建較為美觀的用戶界面,經常要下載一些圖標作為按鈕、控制項等的外觀,甚至需要自己動手製作一些特定的圖標或圖片。自己動力,不得不說需要一定的技術和審美功底;下載,又得到網上到處找,找到一套適合主題、色彩、尺寸、美觀大方的圖標還真是一件不容易的事。

幸好,網上有很多專門下載圖標的網站,常用的有:

http://www.easyicon.net/

https://www.iconfinder.com/

http://www.haotu.net/

http://www.iconpng.com/

http://findicons.com/

http://www.flaticon.com/

http://www.iconspedia.com/

http://icones.pro/

這些網站各有各的優點,共同點是都包含大量圖標,我個人比較喜歡在EasyIcon上去搜索,下載,也很喜歡它的網址。它有優點有:

(1)支持中英文搜索。EasyIcon支持中文和英文的搜索,當然,它的原始圖標名稱還是英文,只不過在搜索前,利用百度翻譯API將中文翻譯成英文,再進行搜索。

(2)用戶體驗好。很多網址在進行瀏覽時,都是需要點擊"下一頁"之類的按鈕,而它支持鍵盤快捷鍵,而且體驗效果還不錯;它的界面、文字啊也比較活潑,比如按熱度排序,它優雅的稱其為"拋頭露面的優先"。

(3)保持更新。作為寫代碼的,我們最害怕開源的東西不再更新了,EasyIcon圖標更新頻率還算將就。

(4)打包下載,有時,我們下載的圖標不只一個,可以使用它的打包下載功能。(但此功能有一定的限制,如每一次打包下載有數量限制,且下載尺寸、格式等不便設置,這也是為什麼要重新寫一個批量下載工具的原因。)

所以,總結下來,我們需要一個程式,實現批量下載不同格式、尺寸的圖標到本地,以便於搜索和利用。

二、方案設計

1.瀏覽器下載圖標

設計方案並不是直接就想出來,還是要根據實際來一點一點地分析、確定。我們用瀏覽器來下載一個圖標試一試。

目標:http://www.easyicon.net/iconsearch/iconset:fatcowhosting-icons/

在這個網址里,包含2000個(40頁)不同尺寸和格式和圖標。fatcowhosting-icons就是這些圖標集合的分類名稱。

單擊第一個圖標,進入其他詳細頁面:http://www.easyicon.net/530832-Zoom_Selection_icon.html,這裡我們可以看到很多參數信息。

點擊PNG圖標下載,我們下載這個圖標。(這一次的下載,就是以後代碼中最內層迴圈的一段代碼。)我們看到了真實的下載地址:http://download.easyicon.net/png/530832/32/

只要我們有這個下載網址,無論在哪個瀏覽器或自定義程式,都可以進行下載。

2.分析下載地址

來看每一頁的地址:

http://www.easyicon.net/iconsearch/iconset:fatcowhosting-icons/1/

fatcowhosting-icons表示圖標集合名稱,1表示頁數

那我們來分析一下這個地址:http://download.easyicon.net/png/530832/32/

這個下載地址可分解為:固定部分+格式+圖標編號+尺寸

再來看一下,下載需要的參數:下載地址+文件保存路徑+文件名稱

綜合分析可以看出,圖標的格式、尺寸、文件保存路徑可以由用戶指定,現在關鍵是缺少圖標編號和文件名稱

假如我們已經知道了圖標編號,並將下載網址輸入到瀏覽器的地址欄中提交,瀏覽器可自動識別出下載的文件名稱,這是為何?說明用戶向伺服器提交這個地址後,伺服器返回了一些消息,其中就包括文件名稱,所以,通過某種編程方式(後面會提到,暫不用著急去查詢),可以獲取到文件名稱

好了,現在唯一缺少的主是圖標編號了。通過觀察網站的其他圖標,可以發現這些編號都是連接的,比如530832是Zoom_Selection_icon的編號,而530831是Zoom_Refresh的編號;再看圖標fatcowhosting-icons集合的每一頁都是50個(最後一頁除外),我們是不可以根據每一個圖標和最後一個圖標的編號來獲取這個圖標集合的所有編號?答案是肯定的。

那我們怎麼來獲取第一個和最後一個的編號?如果我們又通過某種技術手段獲取到這兩上編號了……等等,如果能獲取這兩個編號了,為什麼不獲取直接獲取所有編號呢?是的,通過網頁抓取的某種方法應該可以獲取所有編號

3.畫一個簡單的流程圖

下麵是使用億圖圖示專家V7.9繪製流程圖:

4.寫一個簡單的介面

分析了這麼久,寫一個簡單的介面來理一下我們的思路。(C#)

private string[] FileType;  //文件格式
private int[] FileSize;     //文件大小
private string FilePath;    //文件保存路徑
private int TotalPages;     //圖標總頁數

//獲取圖標總頁數
private int GetTotalPages(string iconsURL) { }
//獲取當前頁的編號
private string[] GetIDs(string pageURL){}

private bool DownICO(string[] fileType, int[] fileSize, int totalPages)
{
    //一層:遍歷每一頁
    for (int i = 0; i < totalPages; i++)
    {
        //獲取當前頁所有編號
        string[] strIDs = GetIDs("PagesURL");
        //兩層:遍歷每一個編號
        for (int j = 0; j < strIDs.Length; j++)
        {
            //三層:遍歷每一種尺寸
            for (int k = 0; k < fileSize.Length; k++)
            {
                //四層:遍歷每一種格式
                for (int m = 0; m < filePath.Length; m++)
                {
                    //生成下載鏈接
                    string downURL = "http://download.easyicon.net/格式/編號/尺寸/";
                    Down(this.FilePath, downURL);
                    //其他操作……
                }
            }//4
        }//3
    }//2
}//1

//下載每一個圖標
private bool Down(string filePath,string downURL){}

  

5.關鍵問題

下麵是代碼中使用的關鍵問題的解決方案:

(1)如果一切參數都能找到,用哪個類或方法來下載?System.Net.WebClient的DownloadFile方法。

(2)怎樣獲取圖標總頁數?根據觀察網頁,每一頁都有"個圖標,翻X頁可看完",X即為總頁數,通過抓取網頁字元串即可;

(3)怎樣獲取每一頁所有圖標的編號?當然還是通過網頁抓取。如下圖,通過審查元素,可以看到每一個圖標的編號和名稱。

(4)怎樣獲取下載圖標的名稱?有兩種方式,一是網頁內容抓取;二是通過根據服務返回的信息來提取。

三、編程實現

編程比較簡單,下麵是網頁操作的兩個比較核心的函數(第一次抓取網頁,不知道這樣好不好)

第一個函數,是通過網頁地址來獲取網頁代碼的。

/// <summary>
/// 根據URL獲取網頁代碼
/// </summary>
/// <param name="strURL">URL地址</param>
/// <returns>網頁代碼字元串</returns>
public static string GetHtmlString(string strURL)
{
    Uri uri = new Uri(strURL);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    Stream stream = response.GetResponseStream();
    string strHtml = "";
    if (stream != null)
    {
        StreamReader sr = new StreamReader(stream);
        strHtml = sr.ReadToEnd();
        sr.Close();
        stream.Close();
        response.Close();
    }
    return strHtml;
}

  

第二個函數主要是根據向伺服器提交圖標的下載鏈接,獲取返回的headers信息,這些信息里就包含了圖標的名稱。

/// <summary>
/// 根據URL獲取headers信息
/// </summary>
/// <param name="URL">URL地址</param>
/// <returns>headers信息列表</returns>
public static Dictionary<string, string> GetHeaders(string URL)
{
    Dictionary<string, string> headerList = new Dictionary<string, string>();
    WebRequest webRequestObject =HttpWebRequest.Create(URL);
    WebResponse responseObject =webRequestObject.GetResponse();
    foreach (string headerKey in responseObject.Headers)
    {
        headerList.Add(headerKey, responseObject.Headers[headerKey]);
    }
    responseObject.Close();
    return headerList;
}

  

問題一:驗證碼問題

編程其實並不是那麼一蹴而就,或多或少會遇到一些之前沒有想到的問題

其中遇到最大的問題是驗證問題。如果大量下載圖標(第一次達166個圖標)時,向伺服器提交下載地址時,它會彈出驗證視窗,下麵是用webBrowser控制項得到的結果。

這是另外一個網頁http://www.easyicon.net/api/captcha/captcha.php返回的結果

解決:一開始的解決思路是去抓包,獲取提交鏈接和內容,就像其他程式讓用戶打碼一樣;後來我就得反正是要打碼,還不如讓用戶直接看到這個頁面(當然,這樣的界面顯示很粗糙,實際上應該去獲取這個圖標,並將這個圖標顯示在用戶面前),於是用了webBrowser控制項;接下來,需要一個輸入,然後提交:輸入採用了VB中的InputBox,這樣更方便,不需要去暫停線程,提交就是用HtmlElement的GetAttribute來獲取提交按鈕,用InvokeMember方法來執行。

問題二:程式假死問題

下載量過多,程式界面肯定會假死,用戶體驗十分不好。需要新建線程,但要註意新線程與主線程之間的控制項信息交互問題。

解決:下麵是用委托來實現向ListBoxAdv添加下載返回的消息的函數。

delegate void SetValueCallback(ListBoxAdv lstA,string log);
private void SetPropertyValue(ListBoxAdv lstA,string log)
{
    if (lstA.InvokeRequired)
    {
        SetValueCallback d = new SetValueCallback(SetPropertyValue);
        lstA.Invoke(d, new object[] { lstA,log });
    }
    else
    {
        lstA.Items.Add(log);
        lstA.SetSelected(lstA.Items.Count-1,true);
        lstA.SelectedIndex=lstA.Items.Count - 1;
    }
}

  

調用:

SetPropertyValue(lstAdv, "消息……”);

  

問題三:下載失敗問題

並不是所有圖標都能正常下載,即使多次反覆下載,它容易出現,下載結果只有25位元組大小的圖標(重覆下載也無效),可能是因為網速的原因。

解決:遍歷所有25位元組的圖標,刪除後重新下載(當然也需要耗時)。

四、成果展示

主界面

下載的圖標

我測試下載了png 32的圖標,約8000多個,本地和雲盤都有,文件以編號+名稱命名,通過編號,我可以再從官網下載到其他需要的圖標,通過名稱可以搜索到需要的圖標。

源碼下載:http://files.cnblogs.com/files/liweis/EasyDown.rar

展望

1.伺服器是怎樣檢測本機連續下載圖標的數量的?是根據IP還是其他,如果搞清它的機制,是否可以通過某種代碼操作跳過它的檢測,而不再使用驗證碼呢?

2.怎樣查詢到圖標集合的名稱,可以通過某種SQL代碼查詢到嗎?如果可以,整個easyicons就不是問題了!


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

-Advertisement-
Play Games
更多相關文章
  • 2016-03-31 張超《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 Linux如何創建一個新進程 1.我們先閱讀理解task_struct數據結構 1235struct task_struct { 1236 v ...
  • 來自系統媽:http://www.xitongma.com 深度技術GHOST win7系統32,64位經典優化版 V2016年3月 系統概述 深度技術ghost win7系統64位經典優化版適用於筆記本、品牌機,也支持組裝相容機,安裝後自動激活,可供品牌機專賣店及普通用戶安裝使用。保留了在區域網辦 ...
  • 介面的出現,是為瞭解決C#中不允許多重繼承的問題。 1、什麼是介面? 我覺得可以把介面理解為對一組方法聲明進行的統一命名,但這些方法沒有提供任何實現。 通過介面,就可以對方法進行統一管理,避免了在每種類型中重覆定義這些方法。 2、如何使用介面來編程 2.1 介面的定義 interface ICust ...
  • 說明 最近在網上下載了一些資料,所有的文件名被加上網站相關信息,導致文件名非常長.再者,我也不喜歡這樣的做法.那麼,就要重新修改文件名,文件還不少,手動修改確實不便.於是就自己寫了個小工具,基本滿足需要了. 下載 "github" "百度雲" 功能 批量替換文件名中內容 按序號批量重命名 源碼 代碼 ...
  • 一. 使用意圖 常常在開發過程中,碰到一個實體上的屬性值,要賦值給另外一個相類似實體屬性時,且屬性有很多的情況。一般不利用工具的話,就要實例化被賦值實體B,然後再將實體A的欄位一個個賦值給B的屬性,單單寫這些沒有技術含量的賦值語句,就要用很大的代碼篇幅。假如做得好一點的話,一般就是利用反射的方式,將 ...
  • 分類:Unity、C#、VS2015 創建日期:2016-04-02 一、簡介 預製體(Prefab,也叫預設)是“存儲在工程視圖(Project View)中”的一種特殊的資源,是一種可重覆使用的游戲對象(GameObject)的容器。 如果在Project中有多個預製體(Prefab),為了容易... ...
  • 下拉框的兩級聯動是我們開發中經常遇到一種情況。比如一個學生管理系統中,根據年級、科目及姓名查詢學生考試成績,年級和科目都是硬碟中的有限數據(資料庫)而學生則可以有用戶手動指定,這時在資料庫中有年級和科目兩張表,每門科目都對應一個年級,所以我們可以用兩個下拉框(Combobox)來存儲年級和科目信息來... ...
  • 分類:Unity、C#、VS2015 創建日期:2016-04-02 一、簡介 利用Unity內置的基本模型和工具,不需要藉助任何其他的三維建模軟體,就可以直接創建出各種3D模型,這是這一章我們首先學習的內容。 當你學會了基本操作技巧後,再進一步利用(3ds Max、Maya、Blender等)專業 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...