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实现通过pil模块对图片格式进行转换的方法
Mar 24 Python
简单介绍Python中用于求最小值的min()方法
May 15 Python
Python正则表达式常用函数总结
Jun 24 Python
Python正则表达式匹配日期与时间的方法
Jul 07 Python
用Python调用win命令行提高工作效率的实例
Aug 14 Python
使用Python的turtle模块画国旗
Sep 24 Python
Python时间差中seconds和total_seconds的区别详解
Dec 26 Python
Python注释、分支结构、循环结构、伪“选择结构”用法实例分析
Jan 09 Python
pycharm中import呈现灰色原因的解决方法
Mar 04 Python
Python爬虫实现vip电影下载的示例代码
Apr 20 Python
Python+OpenCV图像处理——图像二值化的实现
Oct 24 Python
python爬虫--selenium模块
Mar 31 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
仿AS3实现PHP 事件机制实现代码
2011/01/27 PHP
php数组中包含中文的排序方法
2014/06/03 PHP
php导入大量数据到mysql性能优化技巧
2014/12/29 PHP
54个提高PHP程序运行效率的方法
2015/07/19 PHP
如何正确配置Nginx + PHP
2016/07/15 PHP
PHP 500报错的快速解决方法
2016/12/14 PHP
Cookie 注入是怎样产生的
2009/04/08 Javascript
js和html5实现手机端刮刮卡抽奖效果完美兼容android/IOS
2013/11/18 Javascript
Ubuntu中搭建Nodejs开发环境过程分享
2014/06/01 NodeJs
javascript bom是什么及bom和dom的区别
2015/11/26 Javascript
JavaScript脚本库编写的方法
2015/12/09 Javascript
微信QQ的二维码登录原理js代码解析
2016/06/23 Javascript
Angular2开发——组件规划篇
2017/03/28 Javascript
整理关于Bootstrap表单的慕课笔记
2017/03/29 Javascript
selenium 与 chrome 进行qq登录并发邮件操作实例详解
2017/04/06 Javascript
详解webpack + react + react-router 如何实现懒加载
2017/11/20 Javascript
vue插件mescroll.js实现移动端上拉加载和下拉刷新
2019/03/07 Javascript
vue引入微信sdk 实现分享朋友圈获取地理位置功能
2019/07/04 Javascript
基于JavaScript获取base64图片大小
2019/10/18 Javascript
python判断windows系统是32位还是64位的方法
2015/05/11 Python
python技能之数据导出excel的实例代码
2017/08/11 Python
python如何为创建大量实例节省内存
2018/03/20 Python
Python实现求解括号匹配问题的方法
2018/04/17 Python
python三方库之requests的快速上手
2019/03/04 Python
pandas DataFrame运算的实现
2020/06/14 Python
Python装饰器结合递归原理解析
2020/07/02 Python
python使用建议与技巧分享(一)
2020/08/17 Python
python 录制系统声音的示例
2020/12/21 Python
CSS3 中的@keyframes介绍
2014/09/02 HTML / CSS
英文版销售经理个人求职信
2013/11/20 职场文书
入党自我评价优缺点
2014/01/25 职场文书
2015学校师德师风工作总结
2015/04/22 职场文书
中学生勤俭节约倡议书
2015/04/29 职场文书
幼儿园教师个人工作总结2015
2015/05/12 职场文书
新闻稿标题
2015/07/18 职场文书
OpenCV中resize函数插值算法的实现过程(五种)
2021/06/05 Python