突发奇想,以为有时保存网页上的资源很是麻烦,有没有办法输入一个网址就批量抓取对应资源的办法呢。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就随便作的不用在乎)