Python爬虫包 BeautifulSoup  递归抓取实例详解


Posted in Python onJanuary 28, 2017

Python爬虫包 BeautifulSoup  递归抓取实例详解

概要:

爬虫的主要目的就是为了沿着网络抓取需要的内容。它们的本质是一种递归的过程。它们首先需要获得网页的内容,然后分析页面内容并找到另一个URL,然后获得这个URL的页面内容,不断重复这一个过程。

让我们以维基百科为一个例子。

我们想要将维基百科中凯文·贝肯词条里所有指向别的词条的链接提取出来。

# -*- coding: utf-8 -*-
# @Author: HaonanWu
# @Date:  2016-12-25 10:35:00
# @Last Modified by:  HaonanWu
# @Last Modified time: 2016-12-25 10:52:26
from urllib2 import urlopen
from bs4 import BeautifulSoup

html = urlopen('http://en.wikipedia.org/wiki/Kevin_Bacon')
bsObj = BeautifulSoup(html, "html.parser")

for link in bsObj.findAll("a"):
  if 'href' in link.attrs:
    print link.attrs['href']

上面这个代码能够将页面上的所有超链接都提取出来。

/wiki/Wikipedia:Protection_policy#semi
#mw-head
#p-search
/wiki/Kevin_Bacon_(disambiguation)
/wiki/File:Kevin_Bacon_SDCC_2014.jpg
/wiki/San_Diego_Comic-Con
/wiki/Philadelphia
/wiki/Pennsylvania
/wiki/Kyra_Sedgwick

首先,提取出来的URL可能会有一些重复的

其次,有一些URL是我们不需要的,如侧边栏、页眉、页脚、目录栏链接等等。

所以通过观察,我们可以发现所有指向词条页面的链接都有三个特点:

  • 它们都在id是bodyContent的div标签里
  • URL链接不包含冒号
  • URL链接都是以/wiki/开头的相对路径(也会爬到完整的有http开头的绝对路径)
from urllib2 import urlopen
from bs4 import BeautifulSoup
import datetime
import random
import re

pages = set()
random.seed(datetime.datetime.now())
def getLinks(articleUrl):
  html = urlopen("http://en.wikipedia.org"+articleUrl)
  bsObj = BeautifulSoup(html, "html.parser")
  return bsObj.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"]
  if newArticle not in pages:
    print(newArticle)
    pages.add(newArticle)
    links = getLinks(newArticle)

其中getLinks的参数是/wiki/<词条名称>,并通过和维基百科的绝对路径合并得到页面的URL。通过正则表达式捕获所有指向其他词条的URL,并返回给主函数。

主函数则通过调用递归getlinks并随机访问一条没有访问过的URL,直到没有了词条或者主动停止为止。

这份代码可以将整个维基百科都抓取下来

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

pages = set()
def getLinks(pageUrl):
  global pages
  html = urlopen("http://en.wikipedia.org"+pageUrl)
  bsObj = BeautifulSoup(html, "html.parser")
  try:
    print(bsObj.h1.get_text())
    print(bsObj.find(id ="mw-content-text").findAll("p")[0])
    print(bsObj.find(id="ca-edit").find("span").find("a").attrs['href'])
  except AttributeError:
    print("This page is missing something! No worries though!")

  for link in bsObj.findAll("a", href=re.compile("^(/wiki/)")):
    if 'href' in link.attrs:
      if link.attrs['href'] not in pages:
        #We have encountered a new page
        newPage = link.attrs['href']
        print("----------------\n"+newPage)
        pages.add(newPage)
        getLinks(newPage)
getLinks("")

一般来说Python的递归限制是1000次,所以需要人为地设置一个较大的递归计数器,或者用其他手段让代码在迭代1000次之后还能运行。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Python 相关文章推荐
Python实现对字符串的加密解密方法示例
Apr 29 Python
Python实现的凯撒密码算法示例
Apr 12 Python
numpy实现合并多维矩阵、list的扩展方法
May 08 Python
Python开发最牛逼的IDE——pycharm
Aug 01 Python
Python安装Flask环境及简单应用示例
May 03 Python
Django框架创建mysql连接与使用示例
Jul 29 Python
Python Web静态服务器非堵塞模式实现方法示例
Nov 21 Python
PyCharm无法识别PyQt5的2种解决方法,ModuleNotFoundError: No module named 'pyqt5'
Feb 17 Python
深入浅析Python 函数注解与匿名函数
Feb 24 Python
如何在VSCode下使用Jupyter的教程详解
Jul 13 Python
Python常用base64 md5 aes des crc32加密解密方法汇总
Nov 06 Python
利用python查看数组中的所有元素是否相同
Jan 08 Python
python 编程之twisted详解及简单实例
Jan 28 #Python
详解python之简单主机批量管理工具
Jan 27 #Python
Python下的Softmax回归函数的实现方法(推荐)
Jan 26 #Python
在Django同1个页面中的多表单处理详解
Jan 25 #Python
Python heapq使用详解及实例代码
Jan 25 #Python
python3+PyQt5实现使用剪贴板做复制与粘帖示例
Jan 24 #Python
Python调用C++程序的方法详解
Jan 24 #Python
You might like
Centos 6.5系统下编译安装PHP 7.0.13的方法
2016/12/19 PHP
JavaScript去除空格的几种方法
2006/10/03 Javascript
IE8 引入跨站数据获取功能说明
2008/07/22 Javascript
javascript Keycode对照表
2009/10/24 Javascript
javascript KeyDown、KeyPress和KeyUp事件的区别与联系
2009/12/03 Javascript
jQuery hover 延时器实现代码
2011/03/12 Javascript
JQuery1.6 使用方法三
2011/11/23 Javascript
JavaScript实现网页上的浮动广告的简单方法
2013/06/14 Javascript
js操作iframe兼容各种主流浏览器示例代码
2013/07/22 Javascript
jquery 设置元素相对于另一个元素的top值(实例代码)
2013/11/06 Javascript
使用jquery.qrcode生成彩色二维码实例
2014/08/08 Javascript
JS实现生成会变大变小的圆环实例
2015/08/05 Javascript
JS函数的定义与调用方法推荐
2016/05/12 Javascript
AngularJS 中文API参考手册
2016/07/28 Javascript
浅谈jquery的html方法里包含特殊字符的处理
2016/11/30 Javascript
js生成随机数方法和实例
2017/01/17 Javascript
详解nodejs微信公众号开发——6.自定义菜单
2017/04/13 NodeJs
View.post() 不靠谱的地方你知道多少
2017/08/29 Javascript
vue路由对不同界面进行传参及跳转的总结
2019/04/20 Javascript
微信小程序如何访问公众号文章
2019/07/08 Javascript
Vue 组件的挂载与父子组件的传值实例
2020/09/02 Javascript
ant design vue嵌套表格及表格内部编辑的用法说明
2020/10/28 Javascript
[01:30:55]VG vs Mineski Supermajor 败者组 BO3 第三场 6.6
2018/06/07 DOTA
Python简单生成随机数的方法示例
2018/03/31 Python
pandas apply 函数 实现多进程的示例讲解
2018/04/20 Python
Atom的python插件和常用插件说明
2018/07/08 Python
pytorch::Dataloader中的迭代器和生成器应用详解
2020/01/03 Python
国家地理在线商店:Shop National Geographic
2018/06/30 全球购物
澳大利亚个性化儿童礼品网站:Bright Star Kids
2019/06/14 全球购物
中专生毕业自我鉴定
2013/11/01 职场文书
公司业务主管岗位职责
2013/12/07 职场文书
卫生安全检查制度
2014/02/04 职场文书
党日活动总结
2014/05/07 职场文书
村党支部书记承诺书
2014/05/29 职场文书
校运动会广播稿300字
2014/10/07 职场文书
2016年“12.4”法制宣传日活动总结
2016/04/01 职场文书