呵呵,不要被题目给忽悠了啊,我并不具备开发一个足够智能的网络爬虫程序的能力,那我到底要做什么呢?

其实是这样的,目前公司开发了一个门户类型的网站客户端,但是由于数据流比较复杂,性能非常不理想。要解决这个问题其实也不难,那就是加缓存层(计算机领域提速的万能方案就是缓存,不论是硬件还是软件)。当然,你可能还会提到:全站静态化(其实也是缓存的理念)。

后端开发增加缓存层,其实成本不高,很容易就可以把memcache或redis等内存性KV系统引入到当前项目中。一般情况下会设计为:当用户第一次访问某个页面时,把相关数据存储到缓存中,以加速下一次请求的响应速度

这里需要注意的是第一次访问,你大概知道我想说什么了吧?第一次访问的用户就不是亲娘养的了?,谁来保证他们的体验?

我们姑且把这种方案叫做:被动缓存,那么如何使缓存更加的主动呢?最好是数据一旦发生CURD,就立刻映射到缓存层。这里面涉及到缓存颗粒度,缓存的键规则等细节问题,而且对于目前我们公司的项目而言,难度会更大,因为数据的CURD是发生在其他系统中,而这个门户网站客户端只有在访问时才需要与其他系统通信。

那么如何快速的实现主动缓存呢?再回过头来看看文章标题,你应该猜到最终的解决方案了,对,用机器模拟请求,充当这“第一个用户”,姑且称为伪主动缓存吧~~

好吧,说了这么多,总算到今天的主题了:写一个爬虫程序。
我觉得还是有必要再多说一下场景,这里面涉及到具体需求,有助于思考和权衡!

我们的这个爬虫需要从给定的入口页面开始出发,扫描该页面下所有的链接,并继续进行请求,就这样不停的爬下去。当然,如果检测到的链接和当前入口页面的域不同,则丢弃,毕竟我们是为了创建本站缓存而工作的。另外,我们也不需要爬完全部的链接,按照业界的统计,只需要为三级以内的页面创建缓存即可,什么叫三级以内?简单的说,就是从主页出发,三次跳转以内能达到的页面都算三级以内!这样既能最大程度保证用户体验,又可以尽可能的降低内存占用率,而且我们的爬虫程序也会更快的完成任务!何乐而不为?

最后还要说的是,我们采用广度优先规则进行爬行(而不是搜索引擎用的深度优先),原因很简单,可以简化编程模型,并且个人认为更符合伪主动缓存的需求。

开发语言

我选择使用nodejs,当然从文章题目上,你早已知道答案了!nodejs的编程模型可以有效降低该项目的开发难度(避免多线程模型和锁冲突),又最大程度的确保并发性能(毕竟这个项目是网络IO阻塞型),另外,它有很丰满的工具库供我们使用,这样会让开发成本降至最低。

依赖库

  1. request: 用于发起http请求,简化了操作api
  2. htmlparser2: 用于解析取得的html内容,方便抽取url
  3. async: 用于管理代码执行流程
  4. redis: 用于清空redis中的旧缓存(并不是爬虫程序所必须的)

示意图

看,很简单吧,加上nodejs的强大社区,该程序应该三两天就能做完~我会把相关代码放到github上,有兴趣的朋友可去看看。