小白学 Python 爬虫(21):解析库 Beautiful Soup(上)

人生苦短,我用 Python

前文传送门:

小白学 Python 爬虫(1):开篇

小白学 Python 爬虫(2):前置准备(一)基本类库的安装

小白学 Python 爬虫(3):前置准备(二)Linux基础入门

小白学 Python 爬虫(4):前置准备(三)Docker基础入门

小白学 Python 爬虫(5):前置准备(四)数据库基础

小白学 Python 爬虫(6):前置准备(五)爬虫框架的安装

小白学 Python 爬虫(7):HTTP 基础

小白学 Python 爬虫(8):网页基础

小白学 Python 爬虫(9):爬虫基础

小白学 Python 爬虫(10):Session 和 Cookies

小白学 Python 爬虫(11):urllib 基础使用(一)

小白学 Python 爬虫(12):urllib 基础使用(二)

小白学 Python 爬虫(13):urllib 基础使用(三)

小白学 Python 爬虫(14):urllib 基础使用(四)

小白学 Python 爬虫(15):urllib 基础使用(五)

小白学 Python 爬虫(16):urllib 实战之爬取妹子图

小白学 Python 爬虫(17):Requests 基础使用

小白学 Python 爬虫(18):Requests 进阶操作

小白学 Python 爬虫(19):Xpath 基操

小白学 Python 爬虫(20):Xpath 进阶

引言

首先当然是各种资料地址敬上:

先看下官方对自己的介绍:

Beautiful Soup 提供一些简单的、 Python 式的函数来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。

Beautiful Soup 自动将输入文档转换为 Unicode 编码,输出文档转换为 UTF-8 编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时你仅仅需要说明一下原始编码方式就可以了。

Beautiful Soup 已成为和 lxml 、 html6lib 一样出色的 Python 解释器,为用户灵活地提供不同的解析策略或强劲的速度。

讲人话就是 Beautiful Soup 是一个非常好用、速度又快的 HTML 或 XML 的解析库。

Beautiful Soup 在解析时实际上依赖解析器,它除了支持Python标准库中的HTML解析器外,还支持一些第三方解析器。下表列出了主要的解析器,以及它们的优缺点(以下内容来自:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/# ):

解析器 使用方法 优势 劣势
Python 标准库 BeautifulSoup(markup, "html.parser") Python的内置标准库、执行速度适中、文档容错能力强 Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差
lxml HTML 解析器 BeautifulSoup(markup, "lxml") 速度快、文档容错能力强 需要安装C语言库
lxml XML 解析器 BeautifulSoup(markup, ["lxml-xml"])BeautifulSoup(markup, "xml") 速度快、唯一支持XML的解析器 需要安装C语言库
html5lib BeautifulSoup(markup, "html5lib") 最好的容错性、以浏览器的方式解析文档、生成HTML5格式的文档 速度慢、不依赖外部扩展

推荐使用 lxml 作为解析器,因为效率更高。在 Python2.7.3 之前的版本和 Python3 中 3.2.2 之前的版本,必须安装 lxml 或 html5lib ,因为那些 Python 版本的标准库中内置的 HTML 解析方法不够稳定。

提示: 如果一段 HTML 或 XML 文档格式不正确的话,那么在不同的解析器中返回的结果可能是不一样的,查看 解析器之间的区别 了解更多细节。

基本操作

爬取对象还是小编的个人博客(小编看着博客的流量在暗暗心痛)。最基本的,还是先打印首页的 HTML 源码,使用的类库为 Requests + bs4。

import requests
from bs4 import BeautifulSoup response = requests.get('https://www.geekdigging.com/')
soup = BeautifulSoup(response.content, "html5lib")
print(soup.prettify())

结果就不贴了,太长,浪费大家翻页的时间。

首先先解释一下这里为什么选择了 html5lib 的解析器而不是 lxml 的解析器,因为经过小编测试 lxml 的解析器无法解析某些 HTML 标签,经过小编的测试,使用 Python 标准库或者 html5lib 解析器都无此问题,所以这里选择使用 Python 标准库。

上面这段代码主要是调用了 prettify() ,这个方法的主要作用是把要解析的字符串以标准的缩进格式输出。值得注意的是,这里的输出会自动更正 HTML 的格式,但是这一步并不是由 prettify() 这个方法来做的,而是在初始化 BeautifulSoup 时就完成了。

节点选择

我们使用 Beautiful Soup 的目的是什么?当然是要选择我们需要的节点,并从节点中提取出我们需要的数据。

Beautiful Soup 将复杂 HTML 文档转换成一个复杂的树形结构,每个节点都是 Python 对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment

我们直接调用节点的名称就可以选择节点元素,再调用 string 属性就可以得到节点内的文本了,这种选择方式速度非常快。

print(soup.title)
print(type(soup.title))
print(soup.title.string)
print(soup.a)

结果如下:

<title>极客挖掘机</title>
<class 'bs4.element.Tag'>
极客挖掘机
<a class="logo" href="/">
<img src="/favicon.jpg" style="margin-right: 10px;"/>极客挖掘机
</a>

可以看到,我们这里直接输出的 title 节点,它的类型是 bs4.element.Tag ,并且使用 string 属性,直接得到了该节点的内容。

这里我们打印了 a 节点,可以看到,只打印出来了第一个 a 节点,后面的节点并未打印,说明当有多个节点时,这种方式只能获得第一个节点。

获取名称

每个 tag 都有自己的名字,通过 .name 来获取:

tag = soup.section
print(tag.name)

结果如下:

section

获取属性

一个 tag 可能有很多个属性, tag 的属性的操作方法与字典相同:

print(tag['class'])

结果如下:

['content-wrap']

也可以直接”点”取属性, 比如: .attrs

print(tag.attrs)

结果如下:

{'class': ['content-wrap']}

获取内容

可以利用 string 属性获取节点元素包含的文本内容,比如要获取 title 标签的内容:

print(soup.title.string)

结果如下:

极客挖掘机

嵌套选择

在上面的示例中,我们的信息都是从通过 tag 的属性获得的,当然 tag 是可以继续嵌套的选择下去,比如我们刚才获取了第一个 a 标签,我们可以继续获取其中的 img 标签:

print(soup.a.img)
print(type(soup.a.img))
print(soup.a.img.attrs)

结果如下:

<img src="/favicon.jpg" style="margin-right: 10px;"/>
<class 'bs4.element.Tag'>
{'src': '/favicon.jpg', 'style': 'margin-right: 10px;'}

可以看到我们在 a 标签上继续选择的 img 标签,它的类型依然是 bs4.element.Tag ,并且我们成功的获取了 img 标签的属性值,也就是说,我们在 Tag 类型的基础上再次选择得到的依然还是 Tag 类型,所以这样就可以做嵌套选择了。

关联选择

在选择节点的时候,我们很少可以一步到位,直接选到所需要的节点,这就需要我们先选中其中的某一个节点,再已它为基准,再选择它的子节点、父节点或者兄弟节点。

子节点

获取子节点,我们可以选择使用 contents 属性,示例如下:

print(soup.article.contents)

结果太长了,小编就不贴了,这里输出了第一个 article 的所有节点,并且返回结果是列表形式。 article 节点里既包含文本,又包含节点,最后会将它们以列表形式统一返回。

这里需要注意的是,列表中的每个元素都是 article 的直接子节点,并没有将再下一级的元素列出来。而使用 children 也可以得到相同的效果。

for child in enumerate(soup.article.children):
print(child)

结果得到的还是相同的的 HTML 文本,这里调用了 children 属性来选择,返回结果是生成器类型。

想要得到所有的孙子节点的话,可以使用 descendants

for i, child in enumerate(soup.article.descendants):
print(i, child)

父节点

获取父节点可以使用 parent 属性,示例如下:

print(soup.title.parent)

结果有些长,就不贴了,各位同学可以自行尝试一下。

兄弟节点

想要获取兄弟节点可以使用属性 next_siblingprevious_sibling

print('next_sibling:', soup.title.next_sibling)
print('previous_sibling:', soup.title.previous_sibling)
print('next_siblings:', soup.title.next_siblings)
print('previous_siblings:', soup.title.previous_siblings)

结果如下:

next_sibling: 

previous_sibling: 

next_siblings: <generator object PageElement.next_siblings at 0x00000183342C5D48>
previous_siblings: <generator object PageElement.previous_siblings at 0x00000183342C5D48>

可以看到, next_sibling 和 previous_sibling 分别获取节点的下一个和上一个兄弟元素,在这里并没有获取到值,而是获取了很多的空行,这个是在初始化 BeautifulSoup 的时候初始化出来的,而 next_siblings 和 previous_siblings 则分别返回所有前面和后面的兄弟节点的生成器。

示例代码

本系列的所有代码小编都会放在代码管理仓库 Github 和 Gitee 上,方便大家取用。

示例代码-Github

示例代码-Gitee

参考

https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/#

小白学 Python 爬虫(21):解析库 Beautiful Soup(上)的更多相关文章

  1. python爬虫之解析库Beautiful Soup

    为何要用Beautiful Soup Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式, 是一个 ...

  2. 小白学 Python 爬虫(22):解析库 Beautiful Soup(下)

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  3. 小白学 Python 爬虫(23):解析库 pyquery 入门

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  4. 小白学 Python 爬虫(32):异步请求库 AIOHTTP 基础入门

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  5. 小白学 Python 爬虫(25):爬取股票信息

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  6. 小白学 Python 爬虫(26):为啥上海二手房你都买不起

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  7. 小白学 Python 爬虫(29):Selenium 获取某大型电商网站商品信息

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  8. 小白学 Python 爬虫(30):代理基础

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  9. 小白学 Python 爬虫(31):自己构建一个简单的代理池

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

随机推荐

  1. 深度剖析Javascript执行环境、作用域链

    一.执行环境 执行环境(也叫做执行上下文,Execution Context)是Javascript中最为重要的一个概念.执行环境定义了变量或函数有权访问其他数据,决定了它们各自的行为.每个执行环境都 ...

  2. Cognitive Graph for Multi-Hop Reading Comprehension at Scale(ACL2019) 阅读笔记与源码解析

    论文地址为:Cognitive Graph for Multi-Hop Reading Comprehension at Scale github地址:CogQA 背景 假设你手边有一个维基百科的搜索 ...

  3. scrapy介绍及使用

    scrapy的流程 其流程可以描述如下: 调度器把requests-->引擎-->下载中间件--->下载器 下载器发送请求,获取响应---->下载中间件---->引擎-- ...

  4. vue项目中使用百度统计

    统计有多少人访问了自己的网站(wap端pc web端都适用),或者更细的统计网站每个页面的访问量,可以使用百度统计 百度统计传送门 按提示注册登录即可 登录后-->管理-->新增网站,配置 ...

  5. Android加载大量图片内存溢出解决办法

    当我们在做项目过程中,一遇到显示图片时,就要考虑图片的大小,所占内存的大小,原因就是Android分配给Bitmap的大小只有8M,试想想我们用手机拍照,普通的一张照片不也得1M以上,所以androi ...

  6. (四十五)golang--反射

    反射基本介绍: (1)反射可以在运行时动态获取变量的各种信息,比如变量的类型.类别: (2)如果是结构体变量,还可以获取结构体本身的信息(包括结构体字段.方法): (3)通过反射,可以修改变量的值,可 ...

  7. 2019年12月2日Linux开发手记

    开始学习在Linux下视频源捕获驱动框架,也就是V4L2(video4linux),本次关于v4l2的知识准备主要在于其的官方例程,理解官方例程也就差不多掌握了v4l2的基本内容.例程在:http:/ ...

  8. 版本控制神器——git的基本使用

    git基础命令 安装git windows的话,直接下载安装即可 Linux Ubuntu安装,apt-get install git Linux Centos安装,yum install git 配 ...

  9. Machine Learning In Action 第二章学习笔记: kNN算法

    本文主要记录<Machine Learning In Action>中第二章的内容.书中以两个具体实例来介绍kNN(k nearest neighbors),分别是: 约会对象预测 手写数 ...

  10. Linux基本架构

    Linux linux设计思想 1.程序应该小而专一,程序应该尽量的小,且只专注于一件事上,不要开发那些看起来有用但是90%的情况都用不到的特性: 2.程序不只要考虑性能, 程序的可移植性更重要,sh ...