数学之美:图论和网络爬虫

我们上回谈到了怎样创建搜索引擎的索引,那么怎样自动下载互联网所有的网页呢,它要用到图论中的遍历(Traverse) 算法。

图论的起源可追溯到大数学家欧拉(Leonhard Euler)。1736 年欧拉来到德国的哥尼斯堡(Konigsberg,大哲学家康德的家乡,现在是俄罗斯的加里宁格勒),发现当地市民们有一项消遣活动,就是试图将下图中的每座桥正好走过一遍并回到原起点,从来没有人成功过。欧拉证明晰这件事是不行能的,并写了一篇论文,通常以为这是图论的开始。

图论中所讨论的的图由一些节点和连接这些节点的弧组成。如若我们把中国的城市当成节点,连接城市的国道当成弧,那么全国的公路干线网就是图论中所说的图。关于图的算法有许多,但最主要的是图的遍历算法,也就是怎样通过弧访问图的各个节点。

以中国公路网为例,我们从北京出发,看一看北京和哪些城市直接相连,好比说和天津、济南、石家庄、南京、沈阳、大同直接相连。我们可以依次访问这些城市,然后我们看看都有哪些城市和这些已经访问过的城市相连,好比说北戴河、秦皇岛与天津相连,青岛、烟台和济南相连,太原、郑州和石家庄相连等等,我们再一次访问北戴河这些城市,直到中国所有的城市都访问过一遍为止。这种图的遍历算法称为“广度优先算法”(BFS),由于它先要尽可能广地访问每个节点所直接连接的其他节点。

另外另有一种计谋是从北京出发,随便找到下一个要访问的城市,好比是济南,然后从济南出发到下一个城市,好比说南京,再访问从南京出发的城市,一直走到头。然后再往回找,看看中间是否有尚未访问的城市。这种方法叫“深度优先算法”(DFS),由于它是一条路走到黑。这两种方法都可以保证访问到全部的城市。

当然,不论接纳哪种方法,我们都应该用一个小本本,记录已经访问过的城市,以防一个城市访问多次或者遗漏哪个城市。

现在我们看看图论的遍历算法和搜索引擎的关系。

互联网实际上就是一张大图,我们可以把每一个网页看成一个节点,把那些超链接(Hyperlinks)看成连接网页的弧。许多读者可能已经注意到,网页中那些蓝色的、带有下划线的文字背后实际上藏着对应的网址,当你点下去的时间,浏览器是通过这些隐含的网址转到相应的网页中的。这些隐含在文字背后的网址称为“超链接”。有了超链接,我们可以从任何一个网页出发,用图的遍历算法,自动地访问到每一个网页并把它们存起来。完成这个功能的程序叫做网络爬虫,或者在一些文献中称为"机器人"(Robot)。世界上第一个网络爬虫是由麻省理工学院 (MIT)的学生马休.格雷(Matthew Gray)在 1993 年写成的。他给他的程序起了个名字叫“互联网漫游者”("www wanderer")。以后的网络爬虫越写越复杂,但原理是一样的。

我们来看看网络爬虫怎样下载整个互联网。

假定我们从一家门户网站的首页出发,先下载这个网页,然后通过度析这个网页,可以找到藏在它里面的所有超链接,也就等于知道了这家门户网站首页所直接连接的全部网页,诸如雅虎邮件、雅虎财经、雅虎新闻等等。我们接下来访问、下载并剖析这家门户网站的邮件等网页,又能找到其他相连的网页。我们让计算机一直地做下去,就能下载整个的互联网。当然,我们也要纪录哪个网页下载过了,以免重复。在网络爬虫中,我们使用一个称为“哈希表”(Hash Table)的列表而不是一个记事本纪录网页是否下载过的信息。

现在的互联网极度巨大,不能仅通过一台或几台计算机服务器就能完成下载任务。好比雅虎公司(Google 没有公然公布我们的数目,所以我这里举了雅虎的索引大小为例)宣称他们索引了 200 亿个网页,如果下载一个网页需要一秒钟,下载这 200 亿个网页则需要 634 年。因此,一个商业的网络爬虫需要有成千上万个服务器,而且由快速网络连接起来。

怎样创建这样复杂的网络系统,怎样协调这些服务器的任务,就是网络设计和程序设计的艺术了。

原文发布时间为:2015-10-14

时间: 2024-09-02 13:50:20

数学之美:图论和网络爬虫的相关文章

我读经典(1):读《数学之美》有感

        一提到"数学",很多人也许就会感到头痛.确实,在大学的所有课程中,凡是与"数学"有关的课一般逃课率都比较高,当然挂科率也比较的高.可见,大家对"数学"是多么的"厌恶".         但是,我们每天的生活又离不"数学".你到农贸市场去做买卖,需要算账,这是最简单的"数学".作为软件开发人员的我们,需要设计算法,那就更离不开"数学"了."数学

数学之美:平凡又神奇的贝叶斯方法

◆ ◆ ◆ 前言 这是一篇关于贝叶斯方法的科普文,我会尽量少用公式,多用平白的语言叙述,多举实际例子.更严格的公式和计算我会在相应的地方注明参考资料.贝叶斯方法被证明是非常 general 且强大的推理框架,文中你会看到很多有趣的应用. ◆ ◆ ◆ 1.历史 托马斯·贝叶斯(Thomas Bayes)同学的详细生平在这里.以下摘一段 wikipedia 上的简介: 所谓的贝叶斯方法源于他生前为解决一个"逆概"问题写的一篇文章,而这篇文章是在他死后才由他的一位朋友发表出来的.在贝叶斯写这

用Python语言实现网络爬虫

1.什么是网络爬虫 网络爬虫是现代搜索引擎技术的一种非常核心.基础的技术,网络就好比是一张蜘蛛网,网络爬虫就像是一只蜘蛛,在网络间'爬来爬去',搜索有用的信息. 2.抓取代理服务器的网络爬虫 本文介绍用python实现抓取代理服务器的网络爬虫,主要步骤是: 1)利用urllib2获取提供代理服务的网页信息(本文以http://www.cnproxy.com/proxy1.html为例) 2)利用正则表达式获取代理ip信息 3)利用多线程技术验证代理ip的有效性 1).抓取代理ip列表 def g

用Python编写网络爬虫(九):百度贴吧的网络爬虫(v0.4)源码及解析

百度贴吧的爬虫制作和糗百的爬虫制作原理基本相同,都是通过查看源码扣出关键数据,然后将其存储到本地txt文件. 项目内容: 用Python写的百度贴吧的网络爬虫. 使用方法: 新建一个BugBaidu.py文件,然后将代码复制到里面后,双击运行. 程序功能: 将贴吧中楼主发布的内容打包txt存储到本地. 原理解释: 首先,先浏览一下某一条贴吧,点击只看楼主并点击第二页之后url发生了一点变化,变成了: http://tieba.baidu.com/p/2296712428?see_lz=1&pn=

用Python编写网络爬虫(八):糗事百科的网络爬虫(v0.2)源码及解析

项目内容: 用Python写的糗事百科的网络爬虫. 使用方法: 新建一个Bug.py文件,然后将代码复制到里面后,双击运行. 程序功能: 在命令提示行中浏览糗事百科. 原理解释: 首先,先浏览一下糗事百科的主页:http://www.qiushibaike.com/hot/page/1 可以看出来,链接中page/后面的数字就是对应的页码,记住这一点为以后的编写做准备. 然后,右击查看页面源码: 观察发现,每一个段子都用center标记,其中class必为content,title是发帖时间,我

用Python编写网络爬虫(六):一个简单的百度贴吧的小爬虫

# -*- coding: utf-8 -*- #--------------------------------------- # 程序:百度贴吧爬虫 # 版本:0.1 # 作者:why # 日期:2013-05-14 # 语言:Python 2.7 # 操作:输入带分页的地址,去掉最后面的数字,设置一下起始页数和终点页数. # 功能:下载对应页码内的所有页面并存储为html文件. #--------------------------------------- import string,

用Python编写网络爬虫(五):urllib2的使用细节与抓站技巧

前面说到了urllib2的简单入门,下面整理了一部分urllib2的使用细节. 1.Proxy 的设置 urllib2 默认会使用环境变量 http_proxy 来设置 HTTP Proxy. 如果想在程序中明确控制 Proxy 而不受环境变量的影响,可以使用代理. 新建test14来实现一个简单的代理Demo: import urllib2 enable_proxy = True proxy_handler = urllib2.ProxyHandler({"http" : 'http

用Python编写网络爬虫(四):Opener与Handler的介绍和实例应用

在开始后面的内容之前,先来解释一下urllib2中的两个个方法:info and geturl urlopen返回的应答对象response(或者HTTPError实例)有两个很有用的方法info()和geturl() 1.geturl(): 这个返回获取的真实的URL,这个很有用,因为urlopen(或者opener对象使用的)或许会有重定向.获取的URL或许跟请求URL不同. 以人人中的一个超级链接为例, 我们建一个urllib2_test10.py来比较一下原始URL和重定向的链接: fr

用Python编写网络爬虫(三):异常的处理和HTTP状态码的分类

先来说一说HTTP的异常处理问题. 当urlopen不能够处理一个response时,产生urlError. 不过通常的Python APIs异常如ValueError,TypeError等也会同时产生. HTTPError是urlError的子类,通常在特定HTTP URLs中产生. 1.URLError 通常,URLError在没有网络连接(没有路由到特定服务器),或者服务器不存在的情况下产生. 这种情况下,异常同样会带有"reason"属性,它是一个tuple(可以理解为不可变的