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实现udp数据报传输的方法
Sep 26 Python
将Django使用的数据库从MySQL迁移到PostgreSQL的教程
Apr 11 Python
K-近邻算法的python实现代码分享
Dec 09 Python
Python语言描述随机梯度下降法
Jan 04 Python
详解python单元测试框架unittest
Jul 02 Python
用python实现k近邻算法的示例代码
Sep 06 Python
Python使用pandas对数据进行差分运算的方法
Dec 22 Python
在PyCharm下使用 ipython 交互式编程的方法
Jan 17 Python
Python实现的旋转数组功能算法示例
Feb 23 Python
详解字符串在Python内部是如何省内存的
Feb 03 Python
python3.4中清屏的处理方法
Jul 06 Python
selenium自动化测试入门实战
Dec 21 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获得文件扩展名三法
2006/11/25 PHP
19个Android常用工具类汇总
2014/12/30 PHP
CodeIgniter针对lighttpd服务器URL重写的方法
2015/06/10 PHP
PHP机器学习库php-ml的简单测试和使用方法
2017/07/14 PHP
[对联广告] JS脚本类
2006/08/27 Javascript
jquery属性过滤选择器使用示例
2013/06/18 Javascript
用jquery存取照片的具体实现方法
2013/06/30 Javascript
js实现字符串转日期格式的方法
2015/05/20 Javascript
JavaScript操作XML文件之XML读取方法
2015/06/09 Javascript
Javascript复制实例详解
2016/01/28 Javascript
javascript类型系统_正则表达式RegExp类型详解
2016/06/24 Javascript
Ztree新增角色和编辑角色回显问题的解决
2016/10/25 Javascript
SelecT下拉框选中和取值的解决方法
2016/11/22 Javascript
jQuery图片查看插件Magnify开发详解
2017/12/25 jQuery
AngularJS实现动态切换样式的方法分析
2018/06/26 Javascript
JQuery Ajax跨域调用和非跨域调用问题实例分析
2019/04/16 jQuery
layui表格设计以及数据初始化详解
2019/10/26 Javascript
javaScript中indexOf用法技巧
2019/11/26 Javascript
基于JavaScript实现留言板功能
2020/03/16 Javascript
Python遍历zip文件输出名称时出现乱码问题的解决方法
2015/04/08 Python
python用post访问restful服务接口的方法
2018/12/07 Python
python实现AES和RSA加解密的方法
2019/03/28 Python
python time.sleep()是睡眠线程还是进程
2019/07/09 Python
python网络编程 使用UDP、TCP协议收发信息详解
2019/08/29 Python
django中的图片验证码功能
2019/09/18 Python
tensorflow使用freeze_graph.py将ckpt转为pb文件的方法
2020/04/22 Python
matplotlib更改窗口图标的方法示例
2021/02/03 Python
文明青少年标兵事迹材料
2014/01/28 职场文书
评析教师个人的自我评价
2014/02/19 职场文书
三方协议书范本
2014/04/22 职场文书
融资合作协议书范本
2014/10/17 职场文书
出生公证书
2015/01/23 职场文书
个人年终总结怎么写
2015/03/09 职场文书
2015年幼儿园教育教学工作总结
2015/05/25 职场文书
劳动合同变更协议书范本
2019/04/18 职场文书
MongoDB数据库的安装步骤
2021/06/18 MongoDB