我正在尝试编写一个网络爬虫程序,但现在我想知道:存储所有urls的最佳方法是什么,这样爬虫就可以一起工作,但不会干扰。
示例:
我的想法(两种不同的方法)
Crawler扫描页面寻找新的URL Queue实例共享的PriorityQueue( Crawler )中Queue变得太大(例如,最大大小的80% ),就将URL外包给数据库
Crawler保存Analyzer,并在之后搜索URL
问题
Queue是一个瓶颈吗?其他解决方案?
还有别的解决办法吗?什么是web爬虫的标准解决方案?
发布于 2011-12-28 21:46:02
你有不止一个问题要问,但是对于一个一般的方法来说,这个问题怎么样?
请参见这一点,以便讨论确定两个URL是否等效。
那么,你真的有很多选择。我个人的最爱是写三件事。
1)数据库应用程序,它只处理等待访问的URL列表。
2)存储访问站点的重要结果的数据库应用程序。你想救什么都行。
( 3)可以查询并发布到(1),然后发布到(2)的应用程序
,为什么是这样?
你可以把(1)和(2)放在一台机器上。(3)可以在任何地方运行,允许您从多个IP地址运行多个实例。这将帮助您导航服务提供商和其他网络人员,他们可能会对您的重复和频繁的http请求感到不安。
发布于 2012-11-24 19:37:43
虽然这是个老生常谈的问题,但我加入这个答案是为了让搜索者登陆这里
你要找的是一个布卢姆滤波器。
虽然您会发现大多数开放源码筛选器都是为本地访问而设计的库的减少,但实际上将它们转换为web服务,从而成为多个节点的共享资源是相当简单的。
下面是在静态缓存库中使用php-布鲁姆-过滤器的一个非常基本的示例:
<?php
// assumes $_POST contains a JSON-encoded array of URLs to check ($links)
// and a unique crawl identifier ($crawl_id)
extract($_POST);
if (!$b = unserialize(Cache::read('filter_'.$crawl_id))) {
$b = new BloomFilter(100000, 0.001);
}
$return = array();
foreach (json_decode($links, true) as $link) {
if (!$b->has($crawl_id.'_'.$link)) {
$return[] = $link;
$b->add($crawl_id.'_'.$link);
}
}
// put the filter back into our cache
Cache::write('filter_'.$crawl_id, serialize($b));
echo json_encode($return);然后,任何使其脱离筛选器检查的URL都会被推入您的爬行队列中,以便由您的爬行节点进行拾取。
这种实现显然不是为web规模的爬行而设计的,但是对于单个站点最多可爬行100 k或更多(取决于您可用的服务器资源),这种实现是很好的。当然,如果您确实需要花期筛选器来进行水平缩放,那么您可以使用代理后面的多个节点,所有这些节点都使用某种描述的分布式缓存(redis/memcache/ehcache等)。您需要在缓存对象之间进行一些巧妙的切分,以保持查找速度,但我相信您会在需要时解决这个问题。
上面唯一的警告是,您偶尔会得到一个错误的否定,并最终多次爬行相同的URL -这是大多数网络爬虫的事实,所以这只是一个案例,你应该在你的抓取解析代码优雅地处理。
https://stackoverflow.com/questions/8661344
复制相似问题