怎样对链接进行判重?python
Bloom Filter. 简单讲它仍然是一种hash的方法,可是它的特色是,它可使用固定的内存(不随url的数量而增加)以O(1)的效率断定url是否已经在set中。惋惜天下没有白吃的午饭,它的惟一问题在于,若是这个url不在set中,BF能够100%肯定这个url没有看过。可是若是这个url在set中,它会告诉你:这个url应该已经出现过,不过我有2%的不肯定性。注意这里的不肯定性在你分配的内存足够大的时候,能够变得很小不多。一个简单的教程:Bloom Filters by Examplegit
集群化抓取
爬取豆瓣的时候,我总共用了100多台机器昼夜不停地运行了一个月。想象若是只用一台机子你就得运行100个月了...那么,假设你如今有100台机器能够用,怎么用python实现一个分布式的爬取算法呢?
咱们把这100台中的99台运算能力较小的机器叫做slave,另一台较大的机器叫做master,那么回顾上面代码中的url_queue,若是咱们能把这个queue放到这台master机器上,全部的slave均可以经过网络跟master联通,每当一个slave完成下载一个网页,就向master请求一个新的网页来抓取。而每次slave新抓到一个网页,就把这个网页上全部的连接送到master的queue里去。一样,bloom filter也放到master上,可是如今master只发送肯定没有被访问过的url给slave。Bloom Filter放到master的内存里,而被访问过的url放到运行在master上的Redis里,这样保证全部操做都是O(1)。(至少平摊是O(1),Redis的访问效率见:LINSERT – Redis) 考虑如何用python实现:
在各台slave上装好scrapy,那么各台机子就变成了一台有抓取能力的slave,在master上装好Redis和rq用做分布式队列。github
#主、从代码因而写成 #slave.py current_url = request_from_master() to_send = [] for next_url in extract_urls(current_url): to_send.append(next_url) store(current_url); send_to_master(to_send) #master.py distributed_queue = DistributedQueue() bf = BloomFilter() initial_pages = "www.renmingribao.com" while(True): if request == 'GET': if distributed_queue.size()>0: send(distributed_queue.get()) else: break elif request == 'POST': bf.put(request.url)
以上简要示例的具体开源项目:darkrho/scrapy-redis · GitHubredis
展望及后处理
虽然上面用不少“简单”,可是真正要实现一个商业规模可用的爬虫并非一件容易的事。上面的代码用来爬一个总体的网站几乎没有太大的问题。可是若是附加上你须要这些后续处理,好比算法
做者:谢科
连接:https://www.zhihu.com/question/20899988/answer/24923424
来源:知乎
著做权归做者全部,转载请联系做者得到受权。数据库