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的循环体中使用else语句的方法
Mar 30 Python
在Python3中使用asyncio库进行快速数据抓取的教程
Apr 02 Python
Python爬取网易云音乐上评论火爆的歌曲
Jan 19 Python
Python下的Softmax回归函数的实现方法(推荐)
Jan 26 Python
Python Web框架之Django框架Model基础详解
Aug 16 Python
Pandas聚合运算和分组运算的实现示例
Oct 17 Python
学python最电脑配置有要求么
Jul 05 Python
python入门:argparse浅析 nargs='+'作用
Jul 12 Python
Python本地及虚拟解释器配置过程解析
Oct 13 Python
Python环境搭建过程从安装到Hello World
Feb 05 Python
Python实现曲线拟合的最小二乘法
Feb 19 Python
Python如何把不同类型数据的json序列化
Apr 30 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
为IP查询添加GOOGLE地图功能的代码
2010/08/08 PHP
将word转化为swf 如同百度文库般阅读实现思路及代码
2013/08/09 PHP
PHP jQuery表单,带验证具体实现方法
2014/02/15 PHP
PHP使用JSON和将json还原成数组
2015/02/12 PHP
基于PHP+jQuery+MySql实现红蓝(顶踩)投票代码
2015/08/25 PHP
PHP实现支付宝即时到账功能
2016/12/21 PHP
sliderToggle在写jquery的计时器setTimeouter中不生效
2014/05/26 Javascript
兼容主流浏览器的JS复制内容到剪贴板
2014/12/12 Javascript
深入分析jsonp协议原理
2015/09/26 Javascript
Ubuntu系统下Angularjs开发环境安装
2016/09/01 Javascript
Vue数据绑定实例写法
2019/08/06 Javascript
微信小程序激励式视频广告组件使用详解
2019/12/06 Javascript
node.js如何操作MySQL数据库
2020/10/29 Javascript
[57:53]Secret vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
深入浅析python继承问题
2016/05/29 Python
python实现单线程多任务非阻塞TCP服务端
2017/06/13 Python
python和shell获取文本内容的方法
2018/06/05 Python
浅谈解除装饰器作用(python3新增)
2018/10/15 Python
Django REST framework 如何实现内置访问频率控制
2019/07/23 Python
python datetime中strptime用法详解
2019/08/29 Python
python 导入数据及作图的实现
2019/12/03 Python
基于python连接oracle导并出数据文件
2020/04/28 Python
iframe与window.onload如何使用详解
2020/05/07 HTML / CSS
美体小铺英国官网:The Body Shop英国
2017/01/24 全球购物
介绍一下OSI七层模型
2012/07/03 面试题
中专毕业生的自我鉴定
2013/12/01 职场文书
餐饮业创业计划书范文
2014/01/06 职场文书
投资合作协议书范本
2014/04/17 职场文书
小学班长竞选演讲稿
2014/04/24 职场文书
项目投资合作意向书
2014/07/29 职场文书
护士节活动总结
2014/08/29 职场文书
2014教师党员自我评议(5篇)
2014/09/20 职场文书
2014年图书管理员工作总结
2014/12/01 职场文书
2015年销售工作总结范文
2015/03/30 职场文书
Nginx优化服务之网页压缩的实现方法
2021/03/31 Servers
手把手教你使用TensorFlow2实现RNN
2021/07/15 Python