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 08 Python
利用aardio给python编写图形界面
Aug 21 Python
详解python字节码
Feb 07 Python
Python 实现「食行生鲜」签到领积分功能
Sep 26 Python
PyQt5内嵌浏览器注入JavaScript脚本实现自动化操作的代码实例
Feb 13 Python
基于Django框架的权限组件rbac实例讲解
Aug 31 Python
详解Python图像处理库Pillow常用使用方法
Sep 02 Python
TensorFlow梯度求解tf.gradients实例
Feb 04 Python
flask项目集成swagger的方法
Dec 09 Python
python实现三阶魔方还原的示例代码
Apr 28 Python
Python Parser的用法
May 12 Python
一些让Python代码简洁的实用技巧总结
Aug 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
用PHP创建PDF中文文档
2006/10/09 PHP
php下将XML转换为数组
2010/01/01 PHP
thinkphp的静态缓存用法分析
2014/11/29 PHP
php提高网站效率的技巧
2015/09/29 PHP
YII CLinkPager分页类扩展增加显示共多少页
2016/01/29 PHP
浅谈php的TS和NTS的区别
2019/03/13 PHP
PHP的cookie与session原理及用法详解
2019/09/27 PHP
设定php简写功能的方法
2019/11/28 PHP
Node.js中使用socket创建私聊和公聊聊天室
2015/11/19 Javascript
基于匀速运动的实例讲解(侧边栏,淡入淡出)
2017/10/17 Javascript
详解VS Code使用之Vue工程配置format代码格式化
2019/03/20 Javascript
少女风vue组件库的制作全过程
2019/05/15 Javascript
JavaScript设计模型Iterator实例解析
2020/01/22 Javascript
JavaScript实现猜数字游戏
2020/05/20 Javascript
Python urlopen 使用小示例
2008/09/06 Python
Python 文件重命名工具代码
2009/07/26 Python
解决Mac安装scrapy失败的问题
2018/06/13 Python
浅谈python3.6的tkinter运行问题
2019/02/22 Python
python字符串中匹配数字的正则表达式
2019/07/03 Python
Django处理Ajax发送的Get请求代码详解
2019/07/29 Python
python 服务器运行代码报错ModuleNotFoundError的解决办法
2020/09/16 Python
python 发送邮件的四种方法汇总
2020/12/02 Python
使用css3背景渐变中的透明度来设置不同颜色的背景渐变
2014/03/31 HTML / CSS
html5使用canvas压缩图片的示例代码
2018/09/11 HTML / CSS
泰国在线书店:SE-ED
2020/06/21 全球购物
瑞典多品牌连锁店:Johnells
2021/01/13 全球购物
索引覆盖(Index Covering)查询含义
2012/02/18 面试题
请说出这段代码执行后a和b的值分别是多少
2015/03/28 面试题
护理专业毕业生自荐信范文
2014/01/05 职场文书
学生安全责任书
2014/04/15 职场文书
小学标准化建设汇报材料
2014/08/16 职场文书
2014年医生工作总结
2014/11/21 职场文书
中学生综合素质自我评价
2015/03/06 职场文书
幼儿园教师师德师风承诺书
2015/04/28 职场文书
写给消防战士们的一封慰问信
2019/10/07 职场文书
python常见的占位符总结及用法
2021/07/02 Python