實驗:用Unity抓取指定url網頁中的全部圖片並下載保存

突發奇想,以爲有時保存網頁上的資源很是麻煩,有沒有辦法輸入一個網址就批量抓取對應資源的辦法呢。javascript

須要思考的問題:html

1.如何獲得網頁url的html源碼呢?java

2.如何在浩瀚如海的html中匹配出須要的資源地址呢?正則表達式

3.如何按照獲得的資源地址集合批量下載資源呢?瀏覽器

4.下載的資源通常爲文件流,如何生成指定的資源類型並保存呢?服務器

 

須要掌握的知識:網絡

1.網絡爬蟲的基礎知識,發送Http請求的方法測試

2.C# 正則表達式運用,主要是識別html中須要的rul網址url

3.UnityWebRequest類文件流下載線程

4.C# File類和Stream類等基礎文件操做

 

下面分項來進行實現:

關於爬蟲這裏就不進行介紹了,網上其餘的地方有不少資料,簡而言之就是採集網頁信息和數據的程序。

第一步,就是要發送一個Web請求,也能夠說是Http請求。

這跟你打開瀏覽器輸入一個url地址而後回車產生的效果基本是相似的,網頁上之因此能顯示出正確的信息和數據,是由於每個網頁有對應的html源碼,像不少瀏覽器例如谷歌瀏覽器都是支持查看網頁源碼的功能,例以下面是我常常去的喵窩的主頁的html的<head>部分:

 

 

html源碼中能夠查看到網頁當前的不少隱藏信息和數據,其中還有大量的資源連接和樣式表等。值得注意的是,html源碼只有在網頁所有加載完成以後很能夠顯示和查看,這意味着一個url地址的Web請求響應成功;有成功的狀況固然就會有各類各樣失敗的狀況,例如咱們常常輸入一個rul地址後出現404的提示,這種就是一個Http請求出現錯誤的狀況,404表示服務器未找到請求的網頁。其餘的錯誤類型還有不少。爲何要了解這一點呢,由於以後在發送Http請求時要想辦法對錯誤進行處理或跳過執行下一任務。

咱們能夠有不少方式來發送Http請求,Unity也更新了Web請求的方式:(之後代碼我就直接截圖了,這個插入代碼功能都不能自動排整齊真的難受)

 

 

主要用到的類就是UnityWebRequest,和Unity中之前的類WWW有些相似,主要用於文件的下載與上傳。

要引入如下命名空間:

 

 

UnityAction做爲參數主要是用於請求結束後能夠自動返回一個html源碼。它本質上就是個泛型委託:

 

 

泛型的參數能夠從沒有到多個,是一個很是好用的類(尤爲是在協程的回調中,能夠很方便的延時參數傳遞)

固然了,除了Unity內置的發送Web請求的方法,C#也封裝了好幾個類,你能夠隨便挑一個使用,例如 HttpWebRequest,WebClient,HttpClient等:

好比這樣:

 

 

若是成功經過Web請求獲得了指定url地址的html源碼,那就能夠執行下一步了。

第二步,收集html中所須要的數據信息,本例中就是要從這些源碼中找出圖片的連接地址。

例如可能會有下面這幾種狀況:

 

 

 

總結一下,首先利用html的經常使用標籤<img>來找能夠找到大部分的圖片,但仍是有部分圖片並不在這些標籤以內。並且有時候,即便是在<img>標籤以內的圖片地址,仍是有可能出現內鏈或是外鏈的區別,外鏈的話直接做爲合法的url地址執行便可,但若是是內鏈的話就還要補全域名地址,因此咱們還須要想辦法識別一個url的正確域名。

關於如何識別匹配以上所說的字符串內容,目前最有效的方法就是正則表達式,下面就列舉在本例中須要使用到的正則表達式:

1.匹配url域名地址:

private const string URLRealmCheck = @"(http|https)://(www.)?(\w+(\.)?)+";

2.匹配url地址:

private const string URLStringCheck = @"((http|https)://)(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\&%_\./-~-]*)?";

3.匹配html中<img>標籤內的url地址:(不區分大小寫,其中分組<imgUrl>中爲所需的url地址)

private const string imgLableCheck = @"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>";

4.匹配html中<a>標籤內href屬性的url地址:(不區分大小寫,主要用於深度檢索,其中分組<url>中爲所需的url地址)

private const string hrefLinkCheck = @"(?i)<a\s[^>]*?href=(['""]?)(?!javascript|__doPostBack)(?<url>[^'""\s*#<>]+)[^>]*>";

5.指定圖片類型的匹配:(主要用於外鏈)

private const string jpg = @"\.jpg";
private const string png = @"\.png";

關於正則表達式的具體匹配用法,網上也有不少教程,這裏就不說了。

 

給定一個html源碼,這裏從兩個方向進行圖片的匹配,先匹配外鏈,這裏指定了匹配的文件類型:

下面是內鏈的匹配,先要匹配出域名地址:

 

有了域名地址以後就能夠輕鬆匹配內鏈地址了:

 

使用正則表達式須要引入如下命名空間:

 

 

利用正則表達式匹配出全部的imgLinks後就能夠對其中的圖片進行依次下載了。

第三步,對有效的圖片url進行下載傳輸:

 

你也能夠對這些url進行同步下載傳輸,但這樣可能須要增長額外的最大線程數,並且比較難控制總體的下載進度。

具體的傳輸協程以下:

 

值得注意的是,並不是只有成功下載時才調用Complete方法,即便發生了錯誤,也須要調用,這樣避免了一發生錯誤,自動下載就立刻停止。正常狀況下是即便發生了錯誤,也要跳過執行下一文件的下載任務。

 

最後一步就是將下載的數據文件流轉化爲指定類型的文件並保存,這裏方法有不少,下面提供一種:

 

 

擴展:

有時單個html中的全部圖片連接不能徹底知足咱們的需求,由於html中的子連接中可能也會有須要的url資源地址,這時咱們能夠考慮增長更深層次的遍歷。那就須要先匹配出html中的link地址,而後再獲得該link地址的子html源碼,如此進行關於深度匹配的循環。

匹配html中的子連接能夠經過查找<a>標籤的屬性href,上面已經給出過該屬性的正則匹配表達式,這裏只深度匹配了一層以供參考:

 

 

 

測試:這裏用深度匹配抓取喵窩主頁爲jpg格式的圖片連接並下載,存到D盤中。(UI就隨便作的不用在乎)

 

 

 

相關文章
相關標籤/搜索