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 相关文章推荐
Django中使用Celery的教程详解
Aug 24 Python
python截取两个单词之间的内容方法
Dec 25 Python
python linecache 处理固定格式文本数据的方法
Jan 08 Python
selenium+python环境配置教程详解
May 28 Python
PyQt4实时显示文本内容GUI的示例
Jun 14 Python
Django框架之登录后自定义跳转页面的实现方法
Jul 18 Python
Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签
Dec 04 Python
Python3 shelve对象持久存储原理详解
Mar 23 Python
Python中使用threading.Event协调线程的运行详解
May 02 Python
python基础之停用词过滤详解
Apr 21 Python
PyTorch 实现L2正则化以及Dropout的操作
May 27 Python
python中%格式表达式实例用法
Jun 18 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
在PHP3中实现SESSION的功能(二)
2006/10/09 PHP
PHP查询MySQL大量数据的时候内存占用分析
2011/07/22 PHP
ThinkPHP中RBAC类的四种用法分析
2014/11/24 PHP
php使用mysqli向数据库添加数据的方法
2015/03/20 PHP
PHP7新增函数
2021/03/09 PHP
在IE浏览器中resize事件执行多次的解决方法
2011/07/12 Javascript
无刷新预览所选择的图片示例代码
2014/04/02 Javascript
jQuery实现防止提交按钮被双击的方法
2015/03/24 Javascript
Javascript中关于Array.filter()的妙用详解
2016/12/04 Javascript
简单几步实现返回顶部效果
2016/12/05 Javascript
BootStrap 表单控件之单选按钮水平排列
2017/05/23 Javascript
vue2.0 axios前后端数据处理实例代码
2017/06/30 Javascript
Vue computed计算属性的使用方法
2017/07/14 Javascript
js实现QQ面板拖拽效果(慕课网DOM事件探秘)(全)
2017/09/19 Javascript
详解Immutable及 React 中实践
2018/03/01 Javascript
解决layui数据表格排序图标被超出的表头挤出去的问题
2019/09/19 Javascript
使用python解析xml成对应的html示例分享
2014/04/02 Python
Python 执行字符串表达式函数(eval exec execfile)
2014/08/11 Python
python中验证码连通域分割的方法详解
2018/06/04 Python
对Python中class和instance以及self的用法详解
2019/06/26 Python
django 中QuerySet特性功能详解
2019/07/25 Python
Python %r和%s区别代码实例解析
2020/04/03 Python
PyCharm设置Ipython交互环境和宏快捷键进行数据分析图文详解
2020/04/23 Python
tensorflow dataset.shuffle、dataset.batch、dataset.repeat顺序区别详解
2020/06/03 Python
如何使用css3实现一个类在线直播的队列动画的示例代码
2020/06/17 HTML / CSS
Charlotte Tilbury英国官网:英国彩妆品牌
2017/05/26 全球购物
Under Armour瑞典官方网站:美国高端运动科技品牌
2018/11/21 全球购物
介绍一下结构化程序设计方法和面向对象程序设计方法的区别
2012/06/27 面试题
春节联欢会主持词
2014/03/24 职场文书
超市工作总结范文2014
2014/12/19 职场文书
超市采购员岗位职责
2015/04/07 职场文书
活动宣传稿范文
2015/07/23 职场文书
防溺水安全教育主题班会
2015/08/12 职场文书
2020优秀员工演讲稿(三篇)
2019/10/17 职场文书
Java实现HTML转为Word的示例代码
2022/06/28 Java/Android
SQL Server数据库的三种创建方法汇总
2023/05/08 MySQL