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 相关文章推荐
解决出现Incorrect integer value: '' for column 'id' at row 1的问题
Oct 29 Python
单链表反转python实现代码示例
Feb 08 Python
详解Python3.6安装psutil模块和功能简介
May 30 Python
详解pandas.DataFrame中删除包涵特定字符串所在的行
Apr 04 Python
Python中的 sort 和 sorted的用法与区别
Aug 10 Python
详解用Python进行时间序列预测的7种方法
Mar 13 Python
python小程序基于Jupyter实现天气查询的方法
Mar 27 Python
python中rb含义理解
Jun 18 Python
Python如何截图保存的三种方法(小结)
Sep 01 Python
Pyinstaller打包Scrapy项目的实现步骤
Sep 22 Python
Python 流媒体播放器的实现(基于VLC)
Apr 28 Python
Python中文纠错的简单实现
Jul 07 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
叫你如何修改Nginx与PHP的文件上传大小限制
2014/09/10 PHP
PHP编程中的__clone()方法使用详解
2015/11/27 PHP
php中的登陆login实例代码
2016/06/20 PHP
PHP十六进制颜色随机生成器功能示例
2017/07/24 PHP
JQuery select控件的相关操作实现代码
2012/09/14 Javascript
可选择和输入的下拉列表框示例
2013/11/05 Javascript
javascript操作字符串的原生方法
2014/12/22 Javascript
JS实现点击事件统计的简单实例
2016/07/10 Javascript
多功能jQuery树插件zTree实现权限列表简单实例
2016/07/12 Javascript
jquery滚动条插件(可以自定义)
2016/12/11 Javascript
JS实现仿PS的调色板效果完整实例
2016/12/21 Javascript
JS中append字符串包含onclick无效传递参数失败的解决方案
2016/12/26 Javascript
微信小程序 form组件详解及简单实例
2017/01/10 Javascript
ActiveX控件的使用-js实现打印超市小票功能代码详解
2017/11/22 Javascript
JS引用传递与值传递的区别与用法分析
2018/06/01 Javascript
AngularJS $http post 传递参数数据的方法
2018/10/09 Javascript
Vue.js实现可排序的表格组件功能示例
2019/02/19 Javascript
JS块级作用域和私有变量实例分析
2019/05/11 Javascript
NodeJS和浏览器中this关键字的不同之处
2021/03/03 NodeJs
[54:17]DOTA2-DPC中国联赛定级赛 RNG vs iG BO3第二场 1月10日
2021/03/11 DOTA
详解Python验证码识别
2016/01/25 Python
Python 详解基本语法_函数_返回值
2017/01/22 Python
Python基于正则表达式实现检查文件内容的方法【文件检索】
2017/08/30 Python
python中PS 图像调整算法原理之亮度调整
2019/06/28 Python
pandas的qcut()方法详解
2019/07/06 Python
Python正则表达式急速入门(小结)
2019/12/16 Python
瑞典最好的运动鞋专卖店:Sneakersnstuff
2016/08/29 全球购物
西雅图电动自行车公司:Rad Power Bikes
2020/02/02 全球购物
解释一下Windows的消息机制
2014/01/30 面试题
房地产销售经理岗位职责
2014/01/01 职场文书
行政专员的岗位职责
2014/03/10 职场文书
合作意向协议书范本
2014/03/31 职场文书
地球一小时倡议书
2014/04/15 职场文书
大学教师个人总结
2015/02/10 职场文书
2015暑假打工实践报告
2015/07/13 职场文书
spring boot中nativeQuery的用法
2021/07/26 Java/Android