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计算书页码的统计数字问题实例
Sep 26 Python
Python3网络爬虫之使用User Agent和代理IP隐藏身份
Nov 23 Python
Python中staticmethod和classmethod的作用与区别
Oct 11 Python
python requests 库请求带有文件参数的接口实例
Jan 03 Python
Django接收自定义http header过程详解
Aug 23 Python
PyQt5多线程刷新界面防假死示例
Dec 13 Python
python解释器pycharm安装及环境变量配置教程图文详解
Feb 26 Python
python 将视频 通过视频帧转换成时间实例
Apr 23 Python
基于Tensorflow的MNIST手写数字识别分类
Jun 17 Python
Python操作MySQL数据库的示例代码
Jul 13 Python
Python通过类的组合模拟街道红绿灯
Sep 16 Python
Python绘制地图神器folium的新人入门指南
May 23 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
文件系统基本操作类
2006/11/23 PHP
常用表单验证类,有了这个,一般的验证就都齐了。
2006/12/06 PHP
字符串长度函数strlen和mb_strlen的区别示例介绍
2014/09/09 PHP
PHP翻页跳转功能实现方法
2020/11/30 PHP
YII Framework教程之异常处理详解
2016/03/14 PHP
Zend Framework教程之Zend_Config_Ini用法分析
2016/03/23 PHP
php 调用百度sms来发送短信的实现示例
2018/11/02 PHP
怎么用javascript进行拖拽
2006/07/20 Javascript
兼容IE、FireFox、Chrome等浏览器的xml处理函数js代码
2011/11/30 Javascript
通过百度地图获取公交线路的站点坐标的js代码
2012/05/11 Javascript
jQuery实现鼠标滑过遮罩并高亮显示效果
2013/07/16 Javascript
JS实现设置ff与ie元素绝对位置的方法
2016/03/08 Javascript
js使用Replace结合正则替换重复出现的字符串功能示例
2016/12/27 Javascript
AngularJS ng-repeat指令中使用track by子语句解决重复数据遍历错误问题
2017/01/21 Javascript
详解利用jsx写vue组件的方法示例
2017/07/17 Javascript
深入理解vue Render函数
2017/07/19 Javascript
原生JS实现小小的音乐播放器
2017/10/16 Javascript
使用Vue开发动态刷新Echarts组件的教程详解
2018/03/22 Javascript
JS实现调用本地摄像头功能示例
2018/05/18 Javascript
使用webpack搭建vue项目及注意事项
2019/06/10 Javascript
[06:11]2014DOTA2国际邀请赛 专访团结一心的VG战队
2014/07/21 DOTA
[55:54]FNATIC vs EG 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
在GitHub Pages上使用Pelican搭建博客的教程
2015/04/25 Python
Python实现网络端口转发和重定向的方法
2016/09/19 Python
python时间序列按频率生成日期的方法
2019/05/14 Python
python程序运行进程、使用时间、剩余时间显示功能的实现代码
2019/07/11 Python
使用Python绘制台风轨迹图的示例代码
2020/09/21 Python
Pycharm中使用git进行合作开发的教程详解
2020/11/17 Python
python 基于wx实现音乐播放
2020/11/24 Python
好莱坞百老汇御用王牌美妆:Koh Gen Do 江原道
2018/04/03 全球购物
学校后勤岗位职责
2014/02/19 职场文书
大学社团招新的通讯稿
2014/09/10 职场文书
幼儿园安全管理制度
2015/08/05 职场文书
七年级数学教学反思
2016/02/17 职场文书
一篇文章弄懂MySQL查询语句的执行过程
2021/05/07 MySQL
Python基础之元编程知识总结
2021/05/23 Python