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 splitlines使用技巧
Sep 06 Python
python使用win32com库播放mp3文件的方法
May 30 Python
python实现自动获取IP并发送到邮箱
Dec 26 Python
python按照多个条件排序的方法
Feb 08 Python
详解Python并发编程之从性能角度来初探并发编程
Aug 23 Python
django认证系统实现自定义权限管理的方法
Aug 28 Python
利用pandas合并多个excel的方法示例
Oct 10 Python
利用PyCharm操作Github(仓库新建、更新,代码回滚)
Dec 18 Python
如何通过python实现全排列
Feb 11 Python
Python3.x+pyqtgraph实现数据可视化教程
Mar 14 Python
pytorch 计算Parameter和FLOP的操作
Mar 04 Python
Python OpenCV超详细讲解读取图像视频和网络摄像头
Apr 02 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
JQuery从头学起第三讲
2010/07/06 Javascript
js触发asp.net的Button的Onclick事件应用
2013/02/02 Javascript
Web Inspector:关于在 Sublime Text 中调试Js的介绍
2013/04/18 Javascript
深入document.write()与HTML4.01的非成对标签的详解
2013/05/08 Javascript
jQuery中RadioButtonList的功能及用法实例介绍
2013/08/23 Javascript
JQuery控制Radio选中方法分析
2015/05/29 Javascript
JavaScript页面实时显示当前时间实例代码
2016/10/23 Javascript
JavaScript中三种常见的排序方法
2017/02/24 Javascript
关于Vue Webpack2单元测试示例详解
2017/08/14 Javascript
微信小程序使用modal组件弹出对话框功能示例
2017/11/29 Javascript
JS排序算法之冒泡排序,选择排序与插入排序实例分析
2017/12/13 Javascript
VSCode 配置React Native开发环境的方法
2017/12/27 Javascript
JSON的parse()方法介绍
2019/01/31 Javascript
微信小程序地图导航功能实现完整源代码附效果图(推荐)
2019/04/28 Javascript
Angular中innerHTML标签的样式不起作用的原因解析
2019/06/18 Javascript
layui实现checkbox的目录树tree的例子
2019/09/12 Javascript
vue实践---根据不同环境,自动转换请求的url地址操作
2020/09/21 Javascript
基于Vant UI框架实现时间段选择器
2020/12/24 Javascript
初步探究Python程序的执行原理
2015/04/11 Python
Python和Java进行DES加密和解密的实例
2018/01/09 Python
python pands实现execl转csv 并修改csv指定列的方法
2018/12/12 Python
NumPy 基本切片和索引的具体使用方法
2019/04/24 Python
在django中实现页面倒数几秒后自动跳转的例子
2019/08/16 Python
python 上下文管理器及自定义原理解析
2019/11/19 Python
详解Pandas 处理缺失值指令大全
2020/07/30 Python
详解CSS3中强大的filter(滤镜)属性
2017/06/29 HTML / CSS
前端面试必备之html5的新特性
2017/09/05 HTML / CSS
XML文档面试题
2015/08/05 面试题
公司财务工作总结的自我评价
2013/11/23 职场文书
酒店前台接待岗位职责
2013/12/03 职场文书
新闻发布会主持词
2014/03/28 职场文书
创业女性典型材料
2014/05/02 职场文书
检讨书1000字
2014/10/11 职场文书
红旗渠导游词
2015/02/09 职场文书
《狮子和鹿》教学反思
2016/02/16 职场文书
html实现随机点名器的示例代码
2021/04/02 Javascript