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 24 Python
python错误处理详解
Sep 28 Python
用Python的Tornado框架结合memcached页面改善博客性能
Apr 24 Python
Python3中关于cookie的创建与保存
Oct 21 Python
python os.listdir按文件存取时间顺序列出目录的实例
Oct 21 Python
Python基于opencv实现的简单画板功能示例
Mar 04 Python
Python-while 计算100以内奇数和的方法
Jun 11 Python
python SQLAlchemy 中的Engine详解
Jul 04 Python
Python从列表推导到zip()函数的5种技巧总结
Oct 23 Python
详解Python list和numpy array的存储和读取方法
Nov 06 Python
pycharm不能运行.py文件的解决方法
Feb 12 Python
为什么称python为胶水语言
Jun 16 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
星际争霸 Starcraft 游戏介绍
2020/03/14 星际争霸
PHP 类型转换函数intval
2009/06/20 PHP
深入PHP5中的魔术方法详解
2013/06/17 PHP
PHP中的Memcache详解
2014/04/05 PHP
php实现图片等比例缩放代码
2015/07/23 PHP
phpStudy 2016 使用教程详解(支持PHP7)
2017/10/18 PHP
PHP实现微信公众号验证Token的示例代码
2019/12/16 PHP
javascript 实现父窗口引用弹出窗口的值的脚本
2007/08/07 Javascript
jquery命令汇总,方便使用jquery的朋友
2012/06/26 Javascript
如何在JavaScript中实现私有属性的写类方式(二)
2013/12/04 Javascript
利用JS来控制键盘的上下左右键(示例代码)
2013/12/14 Javascript
JQuery实现表格动态增加行并对新行添加事件
2014/07/30 Javascript
一款由jquery实现的整屏切换特效
2014/09/15 Javascript
使用 js+正则表达式为关键词添加链接
2014/11/11 Javascript
Node.js 异步编程之 Callback介绍(一)
2015/03/30 Javascript
Jquery 1.9.1源码分析系列(十二)之筛选操作
2015/12/02 Javascript
jQuery基于BootStrap样式实现无限极地区联动
2016/08/26 Javascript
JavaScript中动态向表格添加数据
2017/01/24 Javascript
Javascript中数组去重与拍平的方法示例
2017/02/03 Javascript
webpack入门+react环境配置
2017/02/08 Javascript
浅谈vue项目如何打包扔向服务器
2018/05/08 Javascript
JS中验证整数和小数的正则表达式
2018/10/08 Javascript
使用AutoJs实现微信抢红包的代码
2020/12/31 Javascript
深入理解python函数递归和生成器
2016/06/06 Python
Python爬取商家联系电话以及各种数据的方法
2018/11/10 Python
Pycharm最常用的快捷键及使用技巧
2020/03/05 Python
Python 3.8 新功能来一波(大部分人都不知道)
2020/03/11 Python
浅谈在JupyterNotebook下导入自己的模块的问题
2020/04/16 Python
python设置表格边框的具体方法
2020/07/17 Python
Windows下Sqlmap环境安装教程详解
2020/08/04 Python
冬季安全检查方案
2014/05/23 职场文书
个人批评与自我批评范文
2014/10/17 职场文书
行政助理岗位职责
2015/02/10 职场文书
学校党支部承诺书
2015/04/30 职场文书
php png失真的原因及解决办法
2021/10/24 PHP
python中filter,map,reduce的作用
2022/06/10 Python