python爬虫之遍历单个域名


Posted in Python onNovember 20, 2019

即使你没听说过“维基百科六度分隔理论”,也很可能听过“凯文 • 贝肯 (Kevin Bacon)的六度分隔值游戏”。在这两个游戏中,目标都是把两 个不相干的主题(在前一种情况中是相互链接的维基百科词条,而在后 一种情况中是出现在同一部电影中的演员)用一个链条(至多包含 6 个 主题,包括原来的两个主题)连接起来。

比如,埃里克 • 艾德尔和布兰登 • 弗雷泽都出现在电影《骑警杜德雷》 里,布兰登 • 弗雷泽又和凯文 • 贝肯都出现在电影《我呼吸的空气》 里。因此,根据这两个条件,从埃里克 • 艾德尔到凯文 • 贝肯的链条 长度只有 3 个主题。

感谢 The Oracle of Bacon 的存在,满足了我对这类关系链的好奇心。

我们将在本节创建一个项目来实现“维基百科六度分隔理论”的查找方 法。也就是说,我们要实现从埃里克 • 艾德尔的词条页面 (https://en.wikipedia.org/wiki/Eric_Idle)开始,经过最少的链接点击次 数找到凯文 • 贝肯的词条页面(https://en.wikipedia.org/wiki/Kevin_Bacon)。

这么做对维基百科的服务器负载有多大影响?

根据维基媒体基金会(维基百科所属的组织)的统计,该网站每秒 会收到大约2500次点击,其中超过 99% 的点击都指向维基百科域 名[详情请见“维基媒体统计图”(Wikimedia in Figures)里的“流量 数据”(Traffic Volume)部分内容]。因为网站流量很大,所以你 的网络爬虫不可能对维基百科的服务器负载产生显著影响。不过, 如果你频繁地运行本书的代码示例,或者自己创建项目来抓取维基 百科的词条,那么希望你能够向维基媒体基金会提供一点捐赠—— 不只是为了抵消你占用的服务器资源,也是为了其他人能够利用维 基百科这个教育资源。

还需要注意的是,如果你准备利用维基百科的数据做一个大型项 目,应该确认该数据是不能够通过维基百科 API 获取的。维基百科 网站经常被用于演示爬虫,因为它的 HTML 结构简单并且相对稳定。但是它的 API 往往会使得数据获取更加高效。 你应该已经知道如何写一段 Python 代码,来获取维基百科网站的任何 页面并提取该页面中的链接了。

from urllib.request import urlopen from bs4 import BeautifulSoup
html = urlopen('http://en.wikipedia.org/wiki/Kevin_Bacon') 
bs = BeautifulSoup(html, 'html.parser') 
for link in bs.find_all('a'):  
if 'href' in link.attrs:    
print(link.attrs['href'])

如果你观察生成的一列链接,会看到你想要的所有词条链接都在里 面:“Apollo 13”“Philadelphia”“Primetime Emmy Award”,等等。但是, 也有一些你不需要的链接:

//wikimediafoundation.org/wiki/Privacy_policy
//en.wikipedia.org/wiki/Wikipedia:Contact_us

其实,维基百科的每个页面都充满了侧边栏、页眉和页脚链接,以及连 接到分类页面、对话页面和其他不包含词条的页面的链接:

/wiki/Category:Articles_with_unsourced_statements_from_April_2014 
/wiki/Talk:Kevin_Bacon

最近我有个朋友在做一个类似的维基百科抓取项目,他说,为了判断一 个维基百科内链是否链接到一个词条页面,他写了一个很大的过滤函 数,代码超过了 100 行。不幸的是,他没有提前花很多时间去寻找“词 条链接”和“其他链接”之间的模式,也可能他后来发现了。如果你仔细 观察那些指向词条页面(不是指向其他内部页面)的链接,会发现它们 都有 3 个共同点:

  • 它们都在 id 是 bodyContent 的 div 标签里
  • URL 不包含冒号
  • URL 都以 /wiki/ 开头

我们可以利用这些规则稍微调整一下代码来仅获取词条链接,使用的正则表达式为 ^(/wiki/)((?!:).)*$")

from urllib.request import urlopen 
from bs4 import BeautifulSoup 
import re
html = urlopen('http://en.wikipedia.org/wiki/Kevin_Bacon') 
bs = BeautifulSoup(html, 'html.parser') 
for link in bs.find('div', {'id':'bodyContent'}).find_all(  
'a', href=re.compile('^(/wiki/)((?!:).)*$')):  
if 'href' in link.attrs:    
print(link.attrs['href'])

如果你运行以上代码,就会看到维基百科上凯文 • 贝肯词条里所有指向 其他词条的链接。

当然,写程序来找出这个静态的维基百科词条里所有的词条链接很有 趣,不过没什么实际用处。你需要让这段程序更像下面的形式。

  • 一个函数 getLinks,可以用一个 /wiki/< 词条名称 > 形式的维 基百科词条 URL 作为参数,然后以同样的形式返回一个列表,里 面包含所有的词条 URL。
  • 一个主函数,以某个起始词条为参数调用 getLinks,然后从返回 的 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{}'.format(articleUrl))  
bs = BeautifulSoup(html, 'html.parser')  
return bs.find('div', {'id':'bodyContent'}).find_all('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 库之后,程序首先做的是用系统当前时间设置随机 数生成器的种子。这样可以保证每次程序运行的时候,维基百科词条的 选择都是一个全新的随机路径。

伪随机数和随机数种子

在前面的示例中,为了能够连续地随机遍历维基百科,我用 Python 的随机数生成器在每个页面上随机选择一个词条链接。但是,用随 机数的时候需要格外小心。

虽然计算机很擅长做精确计算,但是它们处理随机事件时非常不靠 谱。因此,随机数是一个难题。大多数随机数算法都努力生成一个 呈均匀分布且难以预测的数字序列,但是在算法初始化阶段都需要 提供一个随机数“种子”(random seed)。而完全相同的种子每次将 生成同样的“随机”数序列,因此我将系统时间作为生成新随机数序 列(和新随机词条序列)的起点。这样做会让程序运行的时候更具 有随机性。

其实,Python 的伪随机数生成器用的是梅森旋转(Mersenne Twister)算法,它生成的随机数很难预测且呈均匀分布,就是有点 儿耗费 CPU 资源。真正好的随机数可不便宜! 然后,程序定义 getLinks 函数,它接收一个 /wiki/< 词条名称 > 形 式的维基百科词条 URL 作为参数,在前面加上维基百科的域名 http://en.wikipedia.org,再用该域名的 HTML 获得一个 BeautifulSoup 对象。之后,基于前面介绍过的参数,抽取一列词条 链接所在的标签 a 并返回它们。 程序的主函数首先把起始页面 https://en.wikipedia.org/wiki/Kevin_Bacon 里的词条链接列表设置成链接标签列表(links 变量)。然后用一个循 环,从页面中随机找一个词条链接标签并抽取 href 属性,打印这个页 面,再把这个链接传入 getLinks 函数,重新获取新的链接列表。

当然,这里只是简单地构建一个从一个页面到另一个页面的爬虫,要解 决“维基百科六度分隔理论”问题还需要再做一点儿工作。我们还应该存储 URL 链接数据并分析数据。

以上就是关于python爬虫之遍历单个域名的全部知识点,感谢大家的学习和对三水点靠木的支持。

Python 相关文章推荐
Python实现Const详解
Jan 27 Python
Python字符编码判断方法分析
Jul 01 Python
windows 10下安装搭建django1.10.3和Apache2.4的方法
Apr 05 Python
python实现多线程网页下载器
Apr 15 Python
python用户评论标签匹配的解决方法
May 31 Python
Python魔法方法详解
Feb 13 Python
python使用Plotly绘图工具绘制水平条形图
Mar 25 Python
python安装numpy和pandas的方法步骤
May 27 Python
利用Python实现手机短信监控通知的方法
Jul 22 Python
Python实现图像去噪方式(中值去噪和均值去噪)
Dec 18 Python
pytorch 实现tensor与numpy数组转换
Dec 27 Python
Anaconda详细安装步骤图文教程
Nov 12 Python
python matplotlib 画dataframe的时间序列图实例
Nov 20 #Python
python中Lambda表达式详解
Nov 20 #Python
TensorFlow索引与切片的实现方法
Nov 20 #Python
50行Python代码实现视频中物体颜色识别和跟踪(必须以红色为例)
Nov 20 #Python
python中必要的名词解释
Nov 20 #Python
python做接口测试的必要性
Nov 20 #Python
使用NumPy读取MNIST数据的实现代码示例
Nov 20 #Python
You might like
重料打造自己的“宝马”---第三代
2021/03/02 无线电
Zend Studio (eclipse)使用速度优化方法
2011/03/23 PHP
php fputcsv命令 写csv文件遇到的小问题(多维数组连接符)
2011/05/24 PHP
php缩小png图片不损失透明色的解决方法
2013/12/25 PHP
支持中文的PHP按字符串长度分割成数组代码
2015/05/17 PHP
php使用ftp远程上传文件类(完美解决主从文件同步问题的方法)
2016/09/23 PHP
Ajax和PHP正则表达式验证表单及验证码
2016/09/24 PHP
Discuz论坛密码与密保加密规则
2016/12/19 PHP
PHP严重致命错误处理:php Fatal error: Cannot redeclare class or function
2017/02/05 PHP
php格式文件打开的四种方法
2018/02/24 PHP
JS面向对象编程之对象使用分析
2010/08/19 Javascript
JS小功能(onmouseover实现选择月份)实例代码
2013/11/28 Javascript
jquery+css实现绚丽的横向二级下拉菜单-附源码下载
2015/08/23 Javascript
javascript从定义到执行 你不知道的那些事
2016/01/04 Javascript
在Node.js中使用Javascript Generators详解
2016/05/05 Javascript
Javascript基础_标记文字的实现方法
2016/06/14 Javascript
Javascript中prototype的使用详解
2016/06/18 Javascript
[js高手之路]设计模式系列课程-发布者,订阅者重构购物车的实例
2017/08/29 Javascript
详解微信小程序Page中data数据操作和函数调用
2017/09/27 Javascript
解决node-sass偶尔安装失败的方法小结
2018/12/05 Javascript
Vue中Axios从远程/后台读取数据
2019/01/21 Javascript
vue 实现走马灯效果
2019/10/28 Javascript
详解vue中使用transition和animation的实例代码
2020/12/12 Vue.js
python数据结构之二叉树的建立实例
2014/04/29 Python
详解Python自建logging模块
2018/01/29 Python
Python实现的计算马氏距离算法示例
2018/04/03 Python
详解Python下Flask-ApScheduler快速指南
2018/11/04 Python
利用python提取wav文件的mfcc方法
2019/01/09 Python
python爬虫实例之获取动漫截图
2020/05/31 Python
让IE6、IE7、IE8支持CSS3的脚本
2010/07/20 HTML / CSS
Shoes For Crews法国官网:美国领先的防滑鞋设计和制造商
2018/01/01 全球购物
财务管理个人自荐书范文
2013/11/24 职场文书
小学新学期教师寄语
2014/01/18 职场文书
电影雷锋观后感
2015/06/10 职场文书
地震捐款简报
2015/07/21 职场文书
如何使用 resize 实现图片切换预览功能
2021/08/23 HTML / CSS