爬虫是我看过的所有程序中最酷的,因为爬虫可以真正帮你完成一些费事繁琐的工作,比如搜集图片。
咳咳~因为某个网站会把图片打包成种子,发布,并且提供下载,对于老司机来说是省时省力的事情,但是种子是会失效的。有一些很想看的图集想看但是种子失效了,这时候会让人很尴尬,还好,种子没了但是官网图片还在!所以当时就想要是自己写一个爬虫去帮我完成这些另存为图片的工作就好了。
我是想也没想,自己开始筹划。
开始的第一步自然而然是收集一些网页的前端代码(也就是在浏览器里面右键->网页源代码里面查看)。因为我要知道这些网站是不是具有某些规律。
这里就不上图了,因为代码很多(也许大家我会问为什么不去写一个图什么的,匹配到的网址全部扔进去,然而逐个访问不就好了??但是我想说,爬虫不一定搞得非得是一个搜索引擎那样,我们只实现一个功能就不需要股那么多事情了)
是的,我们想要下载的只是图片本身,既然他有规律,我们分析出来直接提取比搜索引擎的哪种方法快很多,而且我们需要的是效率!
看了一下他们网站的结构,大致是:首页 -> 一个图片集的预览页面 –> 预览页面
因为首页里面有很多的图集,但是并不是所有都是我们喜欢的,所以我们设计的程序只需要复制某个图片集的地址,然后帮我们把这个图集的所有图片下载好就行了。
为此,我需要写一个类,帮我们完成分析一个图片集。
这个类的处理对象就是这个本子的预览界面。
我把这个类命名成Spider:
下面是部分代码
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;namespace Spiders
{
public class Spider
{
protected string _uri;//保存指定的起始地址
public Spider(string uri)
{}
}
}
为了避免不必要的维护(设计太多的构造函数重载),我们规定Spider类必须在初始化的时候就指定一个网页地址作为参数。并且使用_uri这个变量存储这里考虑到继承的问题,所以就把string的修饰符改成了Proteced(在原项目的时候并没有考虑到继承,后面发现没有实现继承的话不利于重用)
到这里,我们这个框架算是有个开头了。
接下来我就详细说一下我的实现思路吧。
这个网站的思路是大纲保存这个图片集的标注、图片数量、缩略图等等信息,但是我不能单纯的在大纲页面里面手机图片,因为缩略图他的分辨率是200x134的,这明显不能用来欣赏。随便点击一下其中的图片,他会出现一个预览画面(这不是JQuery的效果,JQuery实现的网页会复杂一些)然后再预览页面里面会保存这个图片的地址,我就想,我初始化Spider类的时候,让他点击第一张图片,进入预览页面然后把每一个预览画面的图片地址缓存下来并且寻找下一页按钮的链接地址就好了。
这里我需要实现一个方法叫做Firststep,顾名思义就是第一步操作,也就是找到这个图片集的第一张图片的预览页面地址,并且返回。
所以这里应该是这样的函数:
protected string FirstStep(string uri)
{
}
然后我们说一下该怎么实现吧!
我们需要下载网页的内容,然后通过正则去匹配。
所以要using System.Net、System.Text.RegularExpressions;这两个命名空间,我们要使用到的类主要有两个,WebClient和Regex
WebClient类的主要作用就是下载文件的(其实就是IE的下载功能一样,效果可能逊色于迅雷很多)我们这里主要使用的是WebClient.DownloadString方法(事实上我使用的是WebClient.OpenToRead方法,因为DownloadString存在编码问题,里面的中文可能会乱码,因为我需要获得正确的中文Title所以我就使用OpenToRead方法。)
而Regex类就是C#里面的正则表达式,我们主要使用的是isMatch、Match。
而正则表达式具体怎么构建,大家还是自行百度吧!(切记,不要相信网上的匹配网址的这则表达式,这东西放C#里面很可能不灵,自己修改的话花费的时间还不如自己去学一遍,入门之后其实写起来也简单。
目前为止,你就实现了一个获得第一张图片的预览页面地址的功能了(很抱歉,这个程序我不能贴代码,因为我就是拿来找小黄片的,贴出来感觉会玩完的,改天我实现一下继承,爬个正经的图片网站,然后再分享代码。求理解)
这里附赠一个自己写的,也可以用的正则^(http|https|bbs)(://)(.+)
但是要说一下,这个正则是分不出到底这个地址是网页地址还是下载地址的,这些都得靠自己去细分。这里推荐一个正则验证工具,因为在Debug的时候才验证正则会费时很多
Regex Match Tracer
之后,要实现的东西就是不断地寻找下一页,并且把这一页的图片下载地址保存起来(你也可以同时下载,WebClient的DownloadFile方法和DownloadFileAsyn方法都可以供你使用,也可以自己活得这个文件的流,然后自己去实现下载功能,但是个人不是很推荐。另外:我要告诉大家的是,DownloadAsyn是异步下载,貌似只有订阅了DownloadFileCompeled事件他进入下载,其次DownloadFile是同步方法,会卡死线程的~除非你要下载的图片没有死链,下载很快,不然真的需要仔细考虑一下该怎么实现下载。反正我要下载的网页存在大部分图片都能下载个别图片丢失的情况。而且要注意错误抛出的捕捉!我是因为太追求成果什么都省略了,但是这样的项目不符合工程规范)。
不断寻找下一页这个实现其实很简单的,不断递归就好了,考虑到不是所有人对递归都辣么熟悉,所以我就把我的递归放出来供大家参考一下
protected void Cicle(string uri)
{
///需要实现的功能
if()//这里填写要退出递归的条件
{
//如果XX满足则递归
Cicle(Next)
}
elsse
{
//否则退出递归
return;
}
//
}
这里就给出了递归的格式,具体是要满足退出还是不满足则退出就要看个人的风格,以及结束循环的条件(这里的条件是以来网站的代码的,我要爬的网站他的特点是无论那一夜他都会有最后一页的链接地址,而其他网页可能到最后一页的时候就只剩下返回上一页的连接可用。这时候只要判断是否只有上一页链接地址可用这个情况就好了,而我的则是判断最后一页是否是当前的网址就可以了。但是我提示一下,下一页一般是用<a>标签,这个时候我们不能像软件编程一样直接判断他是不是enable=false;而正确的做法是吧当前的URI和指定的<a>标签的URI进行对比。
至此这个爬虫框架的开发就告一段落了。
因为这个框架值得LTS,所以我打算一直维护更新这个框架,可以的话我会把代码放到个人的Git或者码云上面,供大家使用。
在声明一次,这个爬虫我用在了不健康的用途,代码也不会贴出来,以免去派出所签到。
但是我还会继续更新的,什么时候我不清楚,或者是我想写一个用于健康用途的网站的时候我再放出来。
谢谢支持!