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

人生苦短,我用 Python
前文传送门:
小白学 Python 爬虫(2):前置准备(一)基本类库的安装
小白学 Python 爬虫(3):前置准备(二)Linux基础入门
小白学 Python 爬虫(4):前置准备(三)Docker基础入门
小白学 Python 爬虫(6):前置准备(五)爬虫框架的安装
小白学 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 爬虫(21):解析库 Beautiful Soup(上)
引言
前面一篇我们介绍的选择方法都是通过属性来进行选择的,这种方法使用起来非常简单,但是,如果 DOM 结构比较复杂的话,这种方法就不是那么友好了。
所以 Beautiful Soup 还为我们提供了一些搜索方法,如 find_all() 和 find() , DOM 节点不好直接用属性方法来表示,我们可以直接搜索嘛~~~
find_all()
先看下语法结构:
find_all( name , attrs , recursive , string , **kwargs )
find_all() 方法搜索当前 tag 的所有 tag 子节点,并判断是否符合过滤器的条件。
name
name 参数可以查找所有名字为 name 的 tag ,字符串对象会被自动忽略掉。
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all(name = "a"))
print(type(soup.find_all(name = "a")[0]))
结果如下:
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
<class 'bs4.element.Tag'>
这次的示例换成了字符串,主要是为了各位同学看起来方便,再也不用去对照着图片看了。
这个示例我们使用了 find_all() 方法,并且传入了 name 参数,值为 a ,含义是我们要查找所有的 <a> 节点,可以看到,返回的结果数据类型是列表,长度为 3 ,并且元素类型为 bs4.element.Tag 。
因为元素类型为 bs4.element.Tag ,我们可以通过前一篇文章介绍的属性直接获取其中的内容:
for a in soup.find_all(name = "a"):
print(a.string)
结果如下:
Elsie
Lacie
Tillie
attrs
除了可以通过 name 进行搜索,我们还可以通过属性进行查询:
print(soup.find_all(attrs={'id': 'link1'}))
print(soup.find_all(attrs={'id': 'link2'}))
print(type(soup.find_all(attrs={'id': 'link1'})))
print(type(soup.find_all(attrs={'id': 'link2'})))
结果如下:
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
[<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
<class 'bs4.element.ResultSet'>
<class 'bs4.element.ResultSet'>
这个示例我们传入的是 attrs 参数,参数的数据类型是字典。
string
这个参数可用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式对象:
import re
print(soup.find_all(text=re.compile('sisters')))
结果如下:
['Once upon a time there were three little sisters; and their names were\n']
keyword
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字 tag 的属性来搜索,比如下面的示例我们直接搜索 id 为 link 的节点和 class 为 title 的节点:
print(soup.find_all(id='link1'))
print(soup.find_all(class_='title'))
结果如下:
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
[<p class="title"><b>The Dormouse's story</b></p>]
当然,我们也可以使用多个指定名字的参数同时过滤 tag 的多个属性:
print(soup.find_all(href=re.compile("elsie"), id='link1'))
结果如下:
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
有些 tag 属性在搜索不能使用,比如 HTML5 中的 data-* 属性,这时就需要用到上面介绍过的 attrs 参数了。
find()
find() 和 find_all() 非常的像,只不过 find() 不再像 find_all() 一样直接返回所有的匹配节点,而是只返回第一个匹配的元素。举几个简单的栗子:
print(soup.find(name = "a"))
print(type(soup.find(name = "a")))
结果如下:
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
<class 'bs4.element.Tag'>
其余的查询方法各位同学可以参考官方文档,小编这里简单列举一下:
find_parents()和find_parent(): 用来搜索当前节点的父辈节点。find_next_siblings()和find_next_sibling(): 前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点。find_previous_siblings()和find_previous_sibling(): 前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点。find_all_next()和find_next():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。find_all_previous()和find_previous():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。
CSS
Beautiful Soup 除了提供前面这些属性选择、搜索方法等方式来获取节点,还提供了另外一种选择器 —— CSS 选择器。
如果对 CSS 选择器不熟的话,可以参考:https://www.w3school.com.cn/css/index.asp 。
使用 CSS 选择器方法非常简单,只需要调用 select() 方法,传入相应的 CSS 选择器即可,还是写几个简单的示例:
print(soup.select('#link1'))
print(type(soup.select('#link1')[0]))
print(soup.select('.story .sister'))
结果如下:
<class 'bs4.element.Tag'>
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
可以看到,我们使用 CSS 选择器获得的结果同样会是一个列表,并且里面的元素同样是 bs4.element.Tag ,这就意味着我们可以使用它的属性来获取对应的信息。
小结
Beautiful Soup 就这么简单的介绍完了,稍微做点小总结:
- 在选择解析器的时候尽量选择
lxml,官方推荐,据说是快。 - 节点属性筛选虽然简单但是功能有点弱鸡。
- find_all() 和 find() 其实可以很方便的帮助我们完成绝大多数的工作。
- CSS 选择器推荐有经验的同学使用,毕竟嘛,选择 DOM 节点,还是 CSS 选择器来的方便好使不是么?
示例代码
本系列的所有代码小编都会放在代码管理仓库 Github 和 Gitee 上,方便大家取用。
参考
https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/#
小白学 Python 爬虫(22):解析库 Beautiful Soup(下)的更多相关文章
- python爬虫之解析库Beautiful Soup
为何要用Beautiful Soup Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式, 是一个 ...
- 小白学 Python 爬虫(21):解析库 Beautiful Soup(上)
小白学 Python 爬虫(21):解析库 Beautiful Soup(上) 人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前 ...
- 小白学 Python 爬虫(23):解析库 pyquery 入门
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(32):异步请求库 AIOHTTP 基础入门
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(25):爬取股票信息
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(26):为啥上海二手房你都买不起
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(29):Selenium 获取某大型电商网站商品信息
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(30):代理基础
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 小白学 Python 爬虫(31):自己构建一个简单的代理池
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
随机推荐
- 《JAVA 程序员面试宝典(第四版)》之循环、条件、概率
分享内容:关于集合的使用 书页号码:77页 题目:一个字符串中包含a~z中的多个字符,如有重复,如String data = "aavzcadfdsfsdhshgwasdfasd ...
- oracle日期时间范围查询
Oracle的日期时间范围查询 字段为:字符串类型(char),长度为:10 SELECT * FROM testdatetime t WHERE = AND t.createdate >= ' ...
- 接口测试之-postman
在使用postman进行接口测试的时候,对于有些接口字段需要时间戳加密,这个时候我们就遇到2个问题,其一是接口中的时间戳如何得到?其二就是对于现在常用的md5加密操作如何在postman中使用代码实现 ...
- Java设计模式之鸭子模式
这两天在看HeadFirst设计模式,第一种鸭子模式都不太理解.后来在百度知道上看了某大神的解释 明白了不少. 列出如下: 假设我们需要设计出各种各样的鸭子,一边游泳戏水, 一边呱呱叫.很明显这时我们 ...
- 【集训Day1 测试】【USACO】照相
照相(fairphoto) [题目描述] 有N 头奶牛站在一条数轴上,第 i 头奶牛的位置是 Pi,奶牛不会重叠站在同一个位置, 第i 头奶牛的颜色是 Ci,其中 Ci 要么是字符'G'要么是字符'H ...
- Linux下用Docker部署接口安全的运行环境
背景:MySQL数据库运行在宿主机上(Linux) 需求:Redis.服务.页面分别运行在独立的docker中,并处于同一网络,容器内部重要目录要挂载在物理目录,保证数据安全 方法: 一.设置网络环境 ...
- mybatis精讲(五)--映射器组件
目录 前言 标签 select insert|update|delete 参数 resultMap cache 自定义缓存 # 加入战队 微信公众号 前言 映射器之前我们已经提到了,是mybatis特 ...
- PHP和JavaScript中奖概率算法
这是一个经典的概率算法. 现在有数组:[10, 20, 30, 40] . 假设对应中奖几率:特等奖10%,一等奖20%,二等奖30%,三等奖40%,总共100%. 算法开始时,从数组中选出一个值$v ...
- 生成n个随机数,要求n个数的和等于100
// 生成n个随机数,要求n个数的和等于100 function lessANumber(n, v) { var i, s = 0, r = [], x = v; for (i = 1; i < ...
- ansible源码安装、普通用户实现批量控制
一.ansible简介 ansible是一款自动化运维工具,基于Python开发,集合了众多运维工具(puppet.chef.func.fabric)的优点,实现了批量系统配置.批量程序部署.批量运行 ...