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 10 Python
Python实现文件内容批量追加的方法示例
Aug 29 Python
Python+OpenCV人脸检测原理及示例详解
Oct 19 Python
教你用 Python 实现微信跳一跳(Mac+iOS版)
Jan 04 Python
Python定义二叉树及4种遍历方法实例详解
Jul 05 Python
Windows10下 python3.7 安装 facenet的教程
Sep 10 Python
python字典setdefault方法和get方法使用实例
Dec 25 Python
Pytorch模型转onnx模型实例
Jan 15 Python
Django自关联实现多级联动查询实例
May 19 Python
完美解决ARIMA模型中plot_acf画不出图的问题
Jun 04 Python
Python3如何使用range函数替代xrange函数
Oct 05 Python
pandas中对文本类型数据的处理小结
Nov 01 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
Zend Framework框架实现类似Google搜索分页效果
2016/11/25 PHP
PHP laravel中的多对多关系实例详解
2017/06/07 PHP
PHP simplexml_import_dom()函数讲解
2019/02/03 PHP
phpcmsv9.0任意文件上传漏洞解析
2020/10/20 PHP
jquery 防止表单重复提交代码
2010/01/21 Javascript
js生成动态表格并为每个单元格添加单击事件的方法
2014/04/14 Javascript
Angularjs实现带查找筛选功能的select下拉框示例代码
2016/10/04 Javascript
jQuery实现级联下拉框实战(5)
2017/02/08 Javascript
深入浅析JSONAPI在PHP中的应用
2017/12/24 Javascript
vue 子组件向父组件传值方法
2018/02/26 Javascript
JS与CSS3实现图片响应鼠标移动放大效果示例
2018/05/04 Javascript
Vue通过getAction的finally来最大程度避免影响主数据呈现问题
2020/04/24 Javascript
[00:48]完美“圣”典2016风云人物:xiao8宣传片
2016/11/30 DOTA
[01:33:30]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第二场 2月5日
2021/03/11 DOTA
简介Django中内置的一些中间件
2015/07/24 Python
python+django+sql学生信息管理后台开发
2018/01/11 Python
python实现机器人行走效果
2018/01/29 Python
TensorFlow saver指定变量的存取
2018/03/10 Python
python numpy--数组的组合和分割实例
2020/02/24 Python
深入CSS3 动画效果的总结详解
2013/05/09 HTML / CSS
分层教学实施方案
2014/03/19 职场文书
小学生中国梦演讲稿
2014/04/23 职场文书
工作会议方案
2014/05/21 职场文书
物资采购方案
2014/06/12 职场文书
明星员工获奖感言
2014/08/14 职场文书
2014年预备党员学习新党章思想汇报
2014/09/15 职场文书
工会2014法制宣传日活动总结
2014/11/01 职场文书
2014年科技工作总结
2014/11/26 职场文书
学雷锋献爱心活动总结
2015/05/11 职场文书
职工宿舍管理制度
2015/08/05 职场文书
Nginx实现高可用集群构建(Keepalived+Haproxy+Nginx)
2021/05/27 Servers
如何理解PHP核心特性命名空间
2021/05/28 PHP
MySQL索引是啥?不懂就问
2021/07/21 MySQL
CSS中实现动画效果-附案例
2022/02/28 HTML / CSS
Go语言 详解net的tcp服务
2022/04/14 Golang
Docker部署Mysql8的实现步骤
2022/07/07 Servers