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通过ajax发起请求返回JSON格式数据的方法
Jun 04 Python
浅谈python迭代器
Nov 08 Python
Python简单实现socket信息发送与监听功能示例
Jan 03 Python
python实现比对美团接口返回数据和本地mongo数据是否一致示例
Aug 09 Python
pygame实现贪吃蛇游戏(上)
Oct 29 Python
python matplotlib画盒图、子图解决坐标轴标签重叠的问题
Jan 19 Python
Python数组并集交集补集代码实例
Feb 18 Python
python:批量统计xml中各类目标的数量案例
Mar 10 Python
Python unittest单元测试openpyxl实现过程解析
May 27 Python
python元组拆包实现方法
Feb 28 Python
用Python爬取各大高校并可视化帮弟弟选大学,弟弟直呼牛X
Jun 11 Python
Python实现仓库管理系统
May 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
xml在joomla表单中的应用详解分享
2012/07/19 PHP
php画图实例
2014/11/05 PHP
PHP永久登录、记住我功能实现方法和安全做法
2015/04/27 PHP
php根据数据id自动生成编号的实现方法
2016/10/16 PHP
作为PHP程序员你要知道的另外一种日志
2018/07/30 PHP
YII框架实现自定义第三方扩展操作示例
2019/04/26 PHP
dojo 之基础篇
2007/03/24 Javascript
javascript StringBuilder类实现
2008/12/22 Javascript
JS中三目运算符和if else的区别分析与示例
2014/11/21 Javascript
jquery图片倾斜层叠切换特效代码分享
2015/08/27 Javascript
node.js使用cluster实现多进程
2016/03/17 Javascript
js显示动态时间的方法详解
2016/08/20 Javascript
详解堆的javascript实现方法
2016/11/29 Javascript
JavaScript正则表达式小结(test|match|search|replace|split|exec)
2016/12/08 Javascript
全面总结Javascript对数组对象的各种操作
2017/01/22 Javascript
Angular+Node生成随机数的方法
2017/06/16 Javascript
js微信应用场景之微信音乐相册案例分享
2017/08/11 Javascript
ubuntu编译nodejs所需的软件并安装
2017/09/12 NodeJs
vue2.0在table中实现全选和反选的示例代码
2017/11/04 Javascript
JS中Map和ForEach的区别
2018/02/05 Javascript
详解webpack之图片引入-增强的file-loader:url-loader
2018/10/08 Javascript
vue + element-ui的分页问题实现
2018/12/17 Javascript
使用Python的Twisted框架构建非阻塞下载程序的实例教程
2016/05/25 Python
python中安装Scrapy模块依赖包汇总
2017/07/02 Python
Python微信公众号开发平台
2018/01/25 Python
Python+PIL实现支付宝AR红包
2018/02/09 Python
python获取微信小程序手机号并绑定遇到的坑
2018/11/19 Python
python中的decimal类型转换实例详解
2019/06/26 Python
Selenium自动化测试工具使用方法汇总
2020/06/12 Python
洛佩桑酒店官方网站:Lopesan Hotels
2019/04/15 全球购物
日语专业推荐信
2013/11/12 职场文书
家长会学生家长演讲稿
2013/12/29 职场文书
欢迎领导检查标语
2014/06/27 职场文书
落实八项规定专题民主生活会对照检查材料
2014/09/15 职场文书
2016年安康杯竞赛活动总结
2016/04/05 职场文书
Opencv实现二维直方图的计算及绘制
2021/07/21 Python