网页抓取数据百度百科( Python感兴趣“入门”点根本不存在!(上))

优采云 发布时间: 2022-04-15 03:13

  网页抓取数据百度百科(

Python感兴趣“入门”点根本不存在!(上))

  

  “开始”是一个很好的动力,但可能会很慢。如果你手头或脑子里有一个项目,在实践中你会被目标驱动,而不是像学习模块那样慢慢学习。

  此外,如果知识系统中的每个知识点都是图中的一个点,并且依赖关系是边,那么图一定不是有向无环图。因为学习A的经验可以帮助你学习B。因此,你不需要学习如何“入门”,因为这样的“入门”点根本不存在!您需要学习的是如何做更大的事情,并且在此过程中,您将很快了解您需要学习的内容。当然,你可以争辩说你需要先了解Python,否则你怎么学Python做爬虫呢?但实际上,你可以在做这个爬虫的过程中学习Python。

  看到前面很多回答中提到的“技能”——用什么软件怎么爬,那我就说说“道”和“技能”——爬虫是如何工作的,以及如何在Python中实现。

  对Python感兴趣的朋友,记得私信小编“007”领取全套Python资料。

  长话短说,总结一下,你需要学习:

  基本爬虫工作原理 基本http爬虫,scrapyBloom Filter 如果需要*敏*感*词*的网页抓取,需要学习分布式爬虫的概念。其实没那么神秘,你只需要学习如何维护一个所有集群机器都可以有效共享的分布式队列。最简单的实现是python-rqrq和scrapy的结合:darkrho/scrapy-redis 后续处理,网页提取 grangier/python-goose,存储(Mongodb)

  这是一个简短的故事:

  说说从我写的一个集群爬下整个豆瓣的经历吧。

  1)首先你需要了解爬虫是如何工作的

  想象一下,你是一只蜘蛛,现在你被放到了互联网“网络”上。好吧,您需要浏览所有网页。怎么做?没问题,你可以从任何地方开始,比如人民日报的首页,称为初始页,用$表示。

  在人民日报的主页上,你会看到各种指向该页面的链接。于是你高高兴兴地爬到了“国内新闻”页面。太好了,你已经爬了两页(首页和国内新闻)!暂时不管你爬下来的页面怎么处理,你可以想象你把这个页面复制成html放到你身上了。

  突然你发现,在国内新闻页面上,有一个返回“首页”的链接。作为一只聪明的蜘蛛,你必须知道你不必爬回来,因为你已经看到了。所以,你需要用你的大脑来保存你已经看过的页面的地址。这样,每次看到可能需要爬取的新链接时,首先在脑海中检查一下是否已经到过这个页面地址。如果你去过,不要去。

  好吧,理论上,如果从初始页面可以到达所有页面,那么就可以证明你可以爬取所有页面。

  那么如何在 Python 中实现呢?非常简单

  import Queue

initial_page = "http://www.renminribao.com"

url_queue = Queue.Queue()

seen = set()

seen.insert(initial_page)

url_queue.put(initial_page)

#一直进行直到海枯石烂

while(True):

if url_queue.size()>0:

#拿出队例中第一个的url

current_url = url_queue.get()

#把这个url代表的网页存储好

store(current_url)

#提取把这个url里链向的url

for next_url in extract_urls(current_url):

if next_url not in seen:

seen.put(next_url)

url_queue.put(next_url)

else:

break

  它已经是非常伪代码了。

  所有爬虫的中坚力量都在这里,我们来分析一下为什么爬虫其实是很复杂的东西——搜索引擎公司通常有一个完整的团队来维护和开发。

  2)效率

  如果你直接处理上面的代码,直接运行,你要花一整年的时间才能爬下豆瓣的全部内容。更不用说像谷歌这样的搜索引擎需要爬取整个内容网络。

  哪里有问题?要爬的页面太多,上面的代码太慢了。假设全网有N个网站,那么分析权重判断的复杂度是N*log(N),因为所有网页都需要遍历一次,需要log(N)的复杂度每次重复使用该集合。. 好的,好的,我知道 Python 的 set 实现是散列 - 但这仍然太慢,至少内存效率不高。

  通常的判断方法是什么?布隆过滤器。简而言之,它仍然是一种哈希方法,但它的特点是可以使用固定内存(不随url的数量增长)来判断url是否已经在集合中,效率为O(1)不幸的是,世界上没有免费的午餐。唯一的问题是如果这个url不在集合中,BF可以100%确定这个url没有被看到。但是如果这个url在设置,它会告诉你:这个 url 应该已经存在了,但是我有 2% 的不确定性。注意,当你分配足够的内存时,这里的不确定性会变得非常小。一个简单的教程:Bloom Filters by Example。

  注意这个特性,如果url看过,可能小概率会重复(没关系,多看就不会累死)。但是如果没有看到,就会看到(这很重要,否则我们会错过一些页面!)。

  好的,现在我们正在接近处理权重的最快方法。另一个瓶颈 - 你只有一台机器。不管你有多少带宽,只要你的机器下载网页的速度是瓶颈,那你就只能提速了。如果一台机器不够用 - 使用多台!当然,我们假设每台机器都进入了最高效率——使用多线程(在 Python 的情况下是多进程)。

  3)集群爬取

  爬豆瓣的时候,我用了100多台机器,24小时不间断地跑了一个月。想象一下,如果你只用一台机器运行 100 个月......

  那么,假设你现在有 100 台机器可用,如何在 Python 中实现分布式爬虫算法呢?

  我们将这100台机器中的99台算力较小的机器称为slave,另一台较大的机器称为master,然后查看上面代码中的url_queue,如果我们可以把这个队列放在这台master机器上,那么所有slave都可以​​与master通信通过网络。每当从站完成下载网页时,它都会向主站请求新的网页以进行爬网。并且每次slave捕获一个新的网页,它会将网页上的所有链接发送到master的队列中。同样,布隆过滤器也放在master上,但是现在master只发送肯定不会被访问的url给slave。Bloom Filter放在master的内存中,访问的url放在运行在master上的Redis中,保证了所有操作都是O(1).(至少摊销是O(1),

  考虑如何在 Python 中做到这一点:

  在每台slave上安装scrapy,然后每台机器都成为具有抓取能力的slave,在master上安装redis和rq作为分布式队列使用。

  然后代码写成

  #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 · GitHub

  4)勘探和后处理

  虽然上面使用了很多“简单”,但要真正实现一个商业规模可用的爬虫并不是一件容易的事。上面的代码用于爬取整个网站,问题不大。

  但是如果附加你需要这些后处理,比如

  有效存储(数据库应该如何安排),有效权重判断(这里指的是网页权重判断,我们不想爬取抄袭它的人民日报和大民日报) 有效信息提取(例如,如何提取所有网页上的信息地址是提取出来的,“朝阳区奋进路中华路”),搜索引擎通常不需要存储所有信息,比如我保存的图片...及时更新(预测此网页多久更新一次)

  可以想象,这里的每一点都可以被许多研究人员研究数十年。即便如此,“路漫漫其修远兮,我要上上下下寻找。”

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线