第一篇我们做了一个简单的页面广度优先来抓取url,很显然缺点有很多,第一:数据结构都是基于内存的,第二:单线程抓取

速度太慢,在实际开发中肯定不会这么做的,起码得要有序列化到硬盘的机制,对于整个爬虫架构来说,构建好爬虫队列相当重要。

先上一幅我自己构思的架构图,不是很完善,算是一个雏形吧。

一:TODO队列和Visited集合

在众多的nosql数据库中,mongodb还是很不错的,这里也就选择它了,做集群,做分片轻而易举。

二:中央处理器

群架,斗殴都是有带头的,那中央处理器就可以干这样的事情,它的任务很简单,

第一: 启动时,根据我们定义好的规则将种子页面分发到各个执行服务器。

第二: 定时轮询”TODO——MongoDB“,将读取的新Url根据规则分发到对应的执行服务器中。

三:分发服务器

中央处理器将url分发到了执行服务器的内存中,分发服务器可以开启10个线程依次读取队列来获取url,然后解析url,

第一:如果url是外链,直接剔除。

第二:如果url不是本机负责抓取的,就放到”TODO——MongoDB“中。

第三:如果是本机负责的,将新提取的url放入本机内存队列中。

四:代码实现

首先下载mongodb http://www.mongodb.org/downloads,简单起见就在一个database里面建两个collection。迫不及

待了,我要爬一个美女网站,http://www.800meinv.com ,申明一下,并非推广网站,看下”中央处理器“的实现。

 1 namespace CrawlerCPU
 2 {
 3     /* 根据规格,一个服务爬取3个导航页(由 中央处理器 统一管理)
 4      * 第一个服务:日韩时装,港台时装
 5      * 第二个服务:,欧美时装,明星穿衣,显瘦搭配
 6      * 第三个服务:少女搭配,职场搭配,裙装搭配
 7      */
 8     public class Program
 9     {
10         static Dictionary<string, string> dicMapping = new Dictionary<string, string>();
11
12         static void Main(string[] args)
13         {
14             //初始Url的分发
15             foreach (var key in ConfigurationManager.AppSettings)
16             {
17                 var factory = new ChannelFactory<ICrawlerService>(new NetTcpBinding(), new EndpointAddress(key.ToString()))
18                                  .CreateChannel();
19
20                 var urls = ConfigurationManager.AppSettings[key.ToString()]
21                                                .Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
22                                                .ToList();
23
24                 factory.AddRange(urls);
25
26                 //将网址和“WCF分发地址“建立Mapping映射
27                 foreach (var item in urls)
28                     dicMapping.Add(item, key.ToString());
29             }
30
31             Console.WriteLine("爬虫 中央处理器开启,正在监视TODO列表!");
32
33             //开启定时监视MongoDB
34             Timer timer = new Timer();
35
36             timer.Interval = 1000 * 10; //10s轮询一次
37             timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
38             timer.Start();
39
40             Console.Read();
41         }
42
43         static void timer_Elapsed(object sender, ElapsedEventArgs e)
44         {
45             //获取mongodb里面的数据
46             MongodbHelper<Message> mongodb = new MongodbHelper<Message>("todo");
47
48             //根据url的类型分发到相应的服务器中去处理
49             var urls = mongodb.List(100);
50
51             if (urls == null || urls.Count == 0)
52                 return;
53
54             foreach (var item in dicMapping.Keys)
55             {
56                 foreach (var url in urls)
57                 {
58                     //寻找正确的 wcf 分发地址
59                     if (url.Url.StartsWith(item))
60                     {
61                         var factory = new ChannelFactory<ICrawlerService>(new NetTcpBinding(),
62                                       new EndpointAddress(dicMapping[item]))
63                                       .CreateChannel();
64
65                         //向正确的地方分发地址
66                         factory.Add(url.Url);
67
68                         break;
69                     }
70                 }
71             }
72
73             //删除mongodb中的TODO表中指定数据
74             mongodb.Remove(urls);
75         }
76     }
77 }

接下来,我们开启WCF服务,当然我们可以做10份,20份的copy,核心代码如下:

 1         /// <summary>
 2         /// 开始执行任务
 3         /// </summary>
 4         public static void Start()
 5         {
 6             while (true)
 7             {
 8                 //监视工作线程,如果某个线程已经跑完数据,则重新分配任务给该线程
 9                 for (int j = 0; j < 10; j++)
10                 {
11                     if (tasks[j] == null || tasks[j].IsCompleted || tasks[j].IsCanceled || tasks[j].IsFaulted)
12                     {
13                         //如果队列还有数据
14                         if (todoQueue.Count > 0)
15                         {
16                             string currentUrl = string.Empty;
17
18                             todoQueue.TryDequeue(out currentUrl);
19
20                             Console.WriteLine("当前队列的个数为:{0}", todoQueue.Count);
21
22                             tasks[j] = Task.Factory.StartNew((obj) =>
23                             {
24                                 DownLoad(obj.ToString());
25
26                             }, currentUrl);
27                         }
28                     }
29                 }
30             }
31         }

然后我们把”分发服务器“和”中央处理器“开启:

好了,稍等会,我们就会看到,数据已经哗啦啦的往mongodb里面跑了。

五:不足点

有的时候会出现某些机器非常free,而某些机器非常busy,这时就要实现双工通讯了,当执行服务器的内存队列到达

一个量级的时候就应该通知中央处理器,要么减缓对该执行服务器的任务分发,要么将任务分给其他的执行服务器。

最后是工程代码,有什么好的建议可以提出来,大家可以一起研究研究:ConsoleApplication1.rar

转载于:https://www.cnblogs.com/huangxincheng/archive/2012/11/04/2754059.html

玩玩小爬虫——试搭小架构相关推荐

  1. 第一只python小爬虫

    前言: 互联网就像一张无形的蜘蛛网,网站就相当于在这张网的交叉结点.而网络爬虫就是这张网上的蜘蛛,它是一种程序,能够利用url链接在各网站之间自动穿梭并抓取所需数据. 学了python的正则表达式之后 ...

  2. Node.js可能是最适合写简易小爬虫的语言,速度极快、代码极少

    "凡是能用JS 写出来的,最终都会用JS 写",这是一个非常著名的定律,用在爬虫这里再合适不过了. 一说到爬虫很多人都会想到python,的确,python语法简洁,还有scrap ...

  3. 微信小程序全面实战,架构设计与躲坑攻略大全

    感谢作者齐修的授权,如需转载,请与作者联系. 作者:齐修,早先就职淘宝UED,目前在好奇心日报参与创业,除了基本的项目开发,还偏好于前端工程化.网站性能优化等方向. 责编:陈秋歌,关注微信开发等领域, ...

  4. 小爬虫sitemap网站seo优化(黄梦岚)

    其实关于SEO优化网络有什么多种的方法,可以通过自己提交链接给百度让网络蜘蛛爬到,也可以使用我这种方法.下面给大家介绍一下小爬虫sitemap网站的seo优化,在这里申明我喜欢的人是黄梦岚(湖南永州东 ...

  5. 使用requests和re模块爬取i春秋论坛的精品贴(小爬虫)

    前言 下一篇是使用requests和re模块爬取某个学习站点的所有用户头像. 最近在刷i春秋论坛的帖子,发现论坛首页每天都会推送一些精品文章,但是有时候好几天也没有更新首页的推送,总不能每天都去刷新吧 ...

  6. python小爬虫SendKey自动刷博刷视频外挂

    python小爬虫SendKey自动刷博刷视频 SendKeys简介 sendkeys是python的一个扩展包,其中有一些常用的符号来表示键盘的快捷键或者输入的字符,对于pywinauto来说,非常 ...

  7. python多线程小爬虫之练练手

    序: 叮咚叮咚,走过路过不要错过啊... 好久没写博客,上次都是几年前了,写过一些android的文章,然而我连账号都忘记了,真尼玛... 大数据时代,人工智能,机器学习开始流行了,赶上了这个时代是好 ...

  8. 打王者、调小酒、搭乐高,大厂女程序员的别样人生

    "良辰三八节,妇女半边天".提到程序员,大家脑海闪现出来的大多数是男性程序员.据Stack Overflow发布的<2021年全球开发者调查报告>显示,在受访的8228 ...

  9. python小爬虫之天气查询

    python小爬虫之天气查询 刚开始研究爬虫,这个小程序通过抓取网页源代码,使用json解析实现了天气的查询. 1.需求分析 该博客实现了简单的天气查询功能,输入城市名称后可以查询出该城市的天气情况. ...

  10. python简单的爬虫教程中召唤小海龟_Python练习,网络小爬虫(初级)

    标签: 最近还在看Python版的rcnn代码,附带练习Python编程写一个小的网络爬虫程序. 抓取网页的过程其实和读者平时使用IE浏览器浏览网页的道理是一样的.比如说你在浏览器的地址栏中输入   ...

最新文章

  1. usr/bin/ld: cannot find 错误解决方法和 /etc/ld.so.conf
  2. 阿里内推题——物流派送员送快递最短路径问题
  3. detectandcompute 图像尺寸太大_基于深度局部特征的图像检索
  4. 关于Android回调的理解
  5. 【OpenJ_Bailian - 2790】迷宫(bfs)
  6. #论char数组结尾’\0’的必要性#
  7. HDU 1010 深搜+奇偶剪枝
  8. 【2017-3-17】视图,事务,备份还原,分离附加
  9. 驱动精灵w8ndows xp sp2,爱普生Epson TM-T90打印机驱动官方正式版下载,适用于winxp,winvista,win7,win8,win10-驱动精灵...
  10. 微信小程序开发工具编辑样式文件后模拟器不显示
  11. 删除EFI系统分区(ESP)后Windows无法启动,重建引导分区并修复启动的过程
  12. 一分钟快速理解:模拟信号和数字信号!
  13. 华三STP、RSTP、MSTP的详解
  14. mybatis lazyload
  15. Valgrind 的下载安装和使用 (centos7.6, 其他linux应该类同)
  16. RFID读卡器增量更新思路与代码实现
  17. 对MySQL进行新建、修改外键级联删除操作
  18. 银河麒麟批量压缩图片的方法
  19. PHP:简单数学勾股定理
  20. 传统公司为什么要开发ERP系统?

热门文章

  1. 获取用户真实IP以及internalProxies
  2. 网站安全之存储型跨站脚本编制
  3. [渝粤教育] 西南科技大学 材料力学 在线考试复习资料
  4. 广度(宽度)优先搜索思路总结
  5. pku 2348 Euclid's Game
  6. 基于OpenCV的红绿灯识别代码解析
  7. sqli-lab(8)
  8. 自家公司关于git commit 的规范
  9. 圣地牙哥『华南理工大学南加州校友会』理事会全体理事及部份校友聚会纪实...
  10. php 判断访问是否是手机或者pc