春满大地,富贵花开。微雨众卉新,一雷惊蛰始。敬请关注微信公众号:AiryData。

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

PYTHON Airy 2152℃ 0评论

预备阅读: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)。

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

1
2
3
4
5
6
7
8
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/开头。

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

1
2
3
4
5
6
7
8
9
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,直到我们主动停止,或者在新的页面上没有词条链接了,程序自动停止。

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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。

转载请注明:数据之美 » Python实现“维基百科六度分隔理论“之基础爬虫

喜欢 (7)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址