Python实现“维基百科六度分隔理论“之基础爬虫

浏览: 1661

预备阅读:Python的urllib高级用法  Python中Beautiful Soup的用法  Python中的正则表达式模块re
前言
前面学习了urllib和beautifulsoup来进行数据采集,相信大家都有了一些基础,如果没有,请看预备阅读,今天来做一个有趣的数据采集,就是遍历一个域名。

最近看了一下六度分隔理论,所以今天用Python来实现“六度分隔理论”的查找方法的基础部分。


六度分隔理论
所谓的“六度分隔理论”,是指世界上任意两个人要想建立联系,最多只需要通过6个人的介绍就能够实现。但根据美国社交网站Facebook最近进行的一项研究,人与人之间的联系相对于以往变得更为紧密,目前只需要4个人的就能把两个互不相识的人联系起来。

1994年,根据约翰·瓜尔(John Guare)的同名戏剧改编的电影《六度分隔》(Six Degrees OfSeparation)上映,“六度分隔理论”得以重新回在人们的视野之中。

同年,演员凯文·贝肯宣称在他漫长而丰富的职业生涯中,他和好莱坞的每一个人都合作过,并因此诞生了一个新的术语——“凯文·贝肯六度理论”。


“维基百科六度分隔理论”
上文提到了凯文·贝肯,根据资料显示,埃里克·艾德尔和布兰登·弗雷泽都出现在电影《骑警杜德雷》里面,布兰登·弗雷泽又和凯文·贝肯同时出现在电影《我呼吸的空气里》。因此,根据这两个条件,从埃里克·艾德尔到凯文·贝肯的链条主题长度只有3。

也就是说,我们要实现从埃里克·艾德尔的词条页(http://en.wikipedia.org/wiki/Eric_Idle)开始,经过最少的链接点击次数找到凯文·贝肯的词条页
http://en.wikipedia.org/wiki/Kevin_Bacon)。

首先我们写一段获取凯文·贝肯词条页的内容的代码:

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("http://en.wikipedia.org/wiki/Kevin_Bacon")
soup = BeautifulSoup(html)
for link in soup.findAll("a"):
    if 'href' in link.attrs:
        print (link.attrs['href'])


上面代码获取的内容会生成一系列链接,我们可以看到我们想要的所有词条链接都在里面,但是这里面页包括的我们不需要的链接,具体内容,请动手操作看一下。

一个网站的每个页面都包括了侧边栏、页眉、页脚等以及分类页面、对话页面和其他链接,维基百科也一样,这是建站的时候为了方便这样做的。
我们仔细看一下指向词条的链接(这里一般F12审查元素找一下规律),会发现它们都有三个共同点:

  • 它们都在id是bodyContent的div标签里。

  • URL链接不包含冒号。

  • URL链接都以/wiki/开头。

下面我们用新规则来稍微调整一下代码:

from urllib.request import urlopen
from bs4 import BeautifulSoup
import re

html = urlopen("http://en.wikipedia.org/wiki/Kevin_Bacon")
soup = BeautifulSoup(html)
for link in soup.find("div", {"id":"bodyContent"}).findAll("a", href = re.compile("^(/wiki/)((?!:).)*$")):
    if 'href' in link.attrs:
        print (link.attrs['href'])

我们运行上面的代码就可以看到维基百科上凯文·贝肯词条里所有指向其他词条的链接。


上面的代码只是获取静态页面的内容,实际意义不大,下面我们来完善一下,看一下具体需求:

  • 一个函数getLinks,可以用维基百科词条/wiki/<词条名称>形式的URL链接作为参数,然后以同样的形式返回一个列表,里面包含所有的词条URL链接。

  • 一个主函数,以某个起始词条为参数调用get    Links,再从返回的URL列表里随机选择一个词条链接,再调用getLinks,直到我们主动停止,或者在新的页面上没有词条链接了,程序自动停止。

完整代码如下:

from urllib.request import urlopen
from bs4 import BeautifulSoup
import datetime
import random
import re

random.seed(datetime.datetime.now())
def getLinks(articleUrl):
    html = urlopen("http://en.wikipedia.org/wiki/Kevin_Bacon")
    soup = BeautifulSoup(html)
    return soup.find("div", {"id":"bodyContent"}).findAll("a", href = re.compile("^(/wiki/)((?!:).)*$"))

links = getLinks("/wiki/Kevin_Bacon")
while len(links) > 0:
    newArticle = links[random.randint(0, len(links)-1)].attrs["href"]
    print (newArticle)
    links = getLinks(newArticle)


上面需要注意的是,导入需要的Python库之后,程序首先做的就是用系统当前时间生成一个随机数生成器,这样可以保证每次在运行程序的时候,维基百科词条的选择都是一个全新的随机路径。

其他执行过程,上面说的很详细了,一一对照即可,这里今天先把最基础的内容,构建从一个页面到另一个页面的爬虫,要解决“维基百科六度分隔理论”还有一部分要做,由于时间问题,今天只能讲到这里,更多精彩,敬请期待。

小结
这里我们重新复习了一下urllib和BeautifulSoup以及正则的用法,加深我们对之前知识的了解,提高问题解决能力,也提出了一个问题,希望感兴趣的同学可以先看看,后面还有高级内容哦。

希望通过上面的内容能帮助大家。如果你有什么好的意见,建议,或者有不同的看法,我都希望你留言和我们进行交流、讨论。
如果想快速联系我,欢迎关注微信公众号:AiryData。

推荐 1
本文由 Airy 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册