Beautiful Soup4
概述
Beautiful Soup是一个Python的库,用于解析HTML和XML文档,提供了方便的数据提取和操作功能。它可以帮助从网页中提取所需的数据,例如标签、文本内容、属性等。
Beautiful Soup会自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。
Beautiful Soup用来解析 HTML比较简单,API非常人性化,支持多种解析器。
文档:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/
文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
主要特点
灵活的解析方式:
Beautiful Soup支持多种解析器,包括Python标准库中的html.parser解析器,以及第三方库lxml和html5lib。这样,我们可以根据需要选择合适的解析器进行处理。
简单直观的API:
Beautiful Soup提供了简洁而友好的API,使得解析HTML文档变得非常容易。我们可以使用简洁的方法来选择特定的标签、获取标签中的文本内容、提取属性值等。
强大的文档遍历能力:
通过Beautiful Soup,我们可以遍历整个HTML文档树,访问、修改或删除各个节点,甚至可以通过嵌套选择器,快速地定位到需要的节点。
对破碎HTML的容错处理:
Beautiful Soup能够处理破碎的HTML文档,例如自动纠正未闭合的标签、自动添加缺失的标签等,使得提取数据更加稳定和可靠。
解析器
Beautiful在解析时依赖解析器,它除了支持Python标准库中的HTML解析器外,还支持一些第三方库。
支持的解析器:
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
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解析器可以解析HTML和XML文档,并且速度快,容错能力强,所有推荐使用它。如果使用lxml,那么在初始化的BeautifulSoup时候,把第二个参数设为lxml即可。
Beautiful Soup4的基本使用
安装库
pip install beautifulsoup4
pip install lxml
创建HTML文件
将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件。
这里创建一个test.html
文件,以此创建一个文档对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<ul>
<li class="class01"><span index="1">H1</span></li>
<li class="class02"><span index="2" class="span2">H2</span></li>
<li class="class03"><span index="3">H3</span></li>
</ul>
</div>
</body>
</html>
基本用法
# 导入模块
from bs4 import BeautifulSoup
# 创建 beautifulsoup对象,有2种方式创建
# 1.通过字符串创建, 第二个参数用于指定解析器
# soup = BeautifulSoup("html", 'lxml')
# 2.通过文件创建
soup = BeautifulSoup(open('test.html'), 'lxml')
# 打印输出
# print(soup.prettify())
# 获取元素标签元素,默认返回第一个元素
print(soup.li)
# 使用 .contents 或 .children 获取子元素
# 返回列表
print(soup.ul.contents)
# 返回迭代器
print(soup.li.children)
# 获取元素内容
print(soup.title.get_text())
# 获取元素属性值,默认取第一个元素属性值
print(soup.li.get('class'))
操作结果如下:
<li class="class01"><span index="1">H1</span></li>
['\n', <li class="class01"><span index="1">H1</span></li>, '\n', <li class="class02"><span class="span2"
index="2">H2</span></li>, '\n', <li class="class03"><span index="3">H3</span></li>, '\n']
<list_iterator object at 0x000001C18E475F10>
Title
['class01']
Beautiful Soup4的对象种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
Tag , NavigableString , BeautifulSoup , Comment
Tag对象
在Beautiful Soup中,Tag对象是用于表示HTML或XML文档中的标签元素的对象,Tag对象与原生文档中的tag相同。Tag对象包含了标签元素的名称、属性和内容等信息,并提供了多种方法来获取、修改和操作这些信息。
soup = BeautifulSoup('<b class="boldest">Extremely bold</b>')
tag = soup.b
type(tag)
# <class 'bs4.element.Tag'>
常用的Tag对象的属性和方法
属性 | 描述 | 示例 |
---|---|---|
name属性 | 获取标签的名称 | tag_name = tag.name |
string属性 | 获取标签内的文本内容 | tag_text = tag.string |
attrs属性 | 获取标签的属性,以字典的形式返回 | tag_attrs = tag.attrs |
get()方法 | 根据属性名获取标签的属性值 | attr_value = tag.get('attribute_name') |
find()方法 | 查找并返回第一个满足条件的子标签元素 | child_tag = tag.find('tag_name') |
find_all()方法 | 查找并返回所有满足条件的子标签元素,以列表的形式返回 | child_tags = tag.find_all('tag_name') |
parent属性 | 获取当前标签的父标签 | parent_tag = tag.parent |
parents属性 | 获取当前标签的所有祖先标签,以生成器的形式返回 | for parent in tag.parents: print(parent) |
children属性 | 获取当前标签的直接子标签,以生成器的形式返回 | for child in tag.children: print(child) |
next_sibling属性 | 获取当前标签的下一个兄弟标签 | next_sibling_tag = tag.next_sibling |
previous_sibling属性 | 获取当前标签的上一个兄弟标签 | previous_sibling_tag = tag.previous_sibling |
NavigableString对象
NavigableString对象是Beautiful Soup库中的一种数据类型,用于表示在HTML或XML文档中的纯文本内容。它继承自Python的基本字符串类型,但具有额外的功能和特性,使其适用于处理文档中的文本内容。
假设有如下HTML代码片段:
<p>This is a <b>beautiful</b> day.</p>
使用Beautiful Soup将其解析为一个文档对象:
from bs4 import BeautifulSoup
html = '<p>This is a <b>beautiful</b> day.</p>'
soup = BeautifulSoup(html, 'html.parser')
获取
标签的内容,这实际上是一个NavigableString对象:
p_tag = soup.find('p')
content = p_tag.string
print(content) # 输出:This is a
print(type(content)) # 输出:<class 'bs4.element.NavigableString'>
还可以对NavigableString对象进行一些操作,如获取文本内容、替换文本以及去除空白字符:
# 获取文本内容
text = content.strip()
print(text) # 输出:This is a
# 替换文本
p_tag.string.replace_with('Hello')
print(p_tag) # 输出:<p>Hello<b>beautiful</b> day.</p>
# 去除空白字符
text_without_spaces = p_tag.string.strip()
print(text_without_spaces) # 输出:Hello
属性 | 描述 | 示例 |
---|---|---|
string属性 | 用于获取NavigableString对象的文本内容 | text = navigable_string.string |
replace_with()方法 | 用于用另一个字符串或对象替换当前NavigableString对象 | navigable_string.replace_with(new_string) |
strip()方法 | 去除字符串两端的空白字符 | stripped_text = navigable_string.strip() |
parent属性 | 获取NavigableString对象所属的父节点(通常是一个Tag对象) | parent_tag = navigable_string.parent |
next_sibling属性 | 获取NavigableString对象的下一个兄弟节点 | next_sibling = navigable_string.next_sibling |
previous_sibling属性 | 获取NavigableString对象的上一个兄弟节点 | previous_sibling = navigable_string.previous_sibling |
BeautifulSoup对象
BeautifulSoup对象是Beautiful Soup库的核心对象,用于解析和遍历HTML或XML文档。
常用方法:
find(name, attrs, recursive, string, **kwargs):根据指定的标签名、属性、文本内容等查找第一个匹配的标签
find_all(name, attrs, recursive, string, limit, **kwargs): 根据指定的标签名、属性、文本内容等查找所有匹配的标签,并返回一个列表
select(css_selector): 使用CSS选择器语法查找匹配的标签,并返回一个列表
prettify():以美观的方式输出整个文档的内容,包括标签、文本和缩进
has_attr(name):检查当前标签是否具有指定的属性名,返回布尔值
get_text():获取当前标签和所有子标签的文本内容,并返回一个字符串
常用属性:
soup.title:获取文档中第一个<title>标签的内容
soup.head:获取文档中的<head>标签
soup.body:获取文档中的<body>标签
soup.find_all('tag'):获取文档中所有匹配的<tag>标签,并返回一个列表
soup.text:获取整个文档中的纯文本内容(去除标签等)
Comment对象
Comment对象是Beautiful Soup库中的一种特殊类型的对象,用于表示HTML或XML文档中的注释内容。
在解析HTML或XML文档时,Beautiful Soup将注释内容作为Comment对象来表示。注释是文档中的一种特殊元素,用于添加注解、说明或暂时删除一部分内容。Comment对象可以通过Beautiful Soup库的解析器自动识别和处理。
处理和访问HTML文档中的注释内容示例:
from bs4 import BeautifulSoup
# 创建包含注释的HTML字符串
html = "<html><body><!-- This is a comment --> <p>Hello, World!</p></body></html>"
# 解析HTML文档
soup = BeautifulSoup(html, 'html.parser')
# 使用type()函数获取注释对象的类型
comment = soup.body.next_sibling
print(type(comment)) # 输出 <class 'bs4.element.Comment'>
# 使用`.string`属性获取注释内容
comment_content = comment.string
print(comment_content) # 输出 This is a comment
搜索文档树
Beautiful Soup提供了多种方式来查找和定位HTML文档中的元素。
方法选择器
使用Beautiful Soup的find()或find_all()方法可以通过标签名、结合属性名和属性值、结合文本内容等方式来选择元素。
两者区别:
find返回符合条件的第一个元素
find_all返回符合条件的所有元素列表
例如:soup.find('div')
会返回第一个div标签的元素,soup.find_all('a')
会返回所有的a标签元素。
1.通过标签或标签列表查找元素
# 查找第一个div标签的元素
soup.find('div')
# 查找所有的a标签元素
soup.find_all('a')
# 查找所有li标签
soup.find_all('li')
# 查找所有a标签和b标签
soup.find_all(['a','b'])
2.通过正则表达式查找元素
# 以sp开头的标签查找
import re
print(soup.find_all(re.compile("^sp")))
3.通过属性查找元素
find = soup.find_all(
attrs={
"属性名":"值"
}
)
print(find)
# 查找第一个具有href属性的a标签元素
soup.find('a', href=True)
# 查找所有具有class属性的div标签元素
soup.find_all('div', class_=True)
4.通过文本内容查找元素
# 查找第一个包含"Hello"文本内容的元素
soup.find(text='Hello')
# 查找所有包含"World"文本内容的元素
soup.find_all(text="World")
5.通过关键词参数查找元素
soup.find_all(id='id01')
6.混合使用
soup.find_all(
'标签名',
attrs={
"属性名":"值"
},
text="内容"
)
CSS选择器
使用Beautiful Soup的select()方法可以通过CSS选择器来查找元素。CSS选择器是一种强大而灵活的方式,可以根据标签名、类名、ID、属性以及它们的组合来定位元素。
1.类选择器
通过类名查找元素,使用
.
符号加上类名来查找元素
soup.select('.className')
2.ID选择器
通过ID查找元素,使用
#
符号加上ID来查找元素soup.select('#id')
3.标签选择器
通过标签名查找元素,直接使用标签名来查找元素
soup.select('p')
4.属性选择器
通过属性查找元素:可以使用
[属性名=属性值]
的格式来查找具有特定属性及属性值的元素
soup.select('[属性="值"]')
soup.select('[href="example.com"]')
soup.select('a[href="http://baidu.com"]')
5.组合选择器
可以将多个选择器组合在一起以获得更精确的查找
# 返回所有在具有特定类名的div元素内的a标签元素
soup.select('div.class01 a')
soup.select('div a')
关联选择
在进行元素查找的过程中,有时候不能做到一步就获取到想要的节点元素,需要选取某一个节点元素,然后以这个节点为基准再选取它的子节点、父节点、兄弟节点等。
在Beautiful Soup中,可以通过使用CSS选择器语法来进行关联选择,需要借助Beautiful Soup的select()方法,它允许使用CSS选择器来选择元素。
1.后代选择器(空格):可以选择指定元素下的所有后代元素。
div a /* 选择div元素下的所有a元素 */
.container p /* 选择类名为container的元素下的所有p元素 */
2.直接子代选择器(>):可以选择指定元素的直接子代元素。
div > a /* 选择div元素的直接子代的a元素 */
.container > p /* 选择类名为container的元素的直接子代的p元素 */
3.相邻兄弟选择器(+):可以选择与指定元素紧邻的下一个同级元素。
h1 + p /* 选择紧接在h1元素后的同级p元素 */
.container + p /* 选择紧接在类名为container的元素后的同级p元素 */
4.通用兄弟选择器(~):可以选择与指定元素同级的所有后续元素。
h1 ~ p /* 选择与h1元素同级的所有p元素 */
.container ~ p /* 选择与类名为container的元素同级的所有p元素 */
5.混合选择器:可以结合多个不同类型的选择器来选择特定的元素
div , p /* 选择所有div元素和所有p元素 */
.cls1.cls2 /* 选择类名是cls1并且类名是cls2 */
遍历文档树
在Beautiful Soup中,遍历文档树是一种常见的操作,用于访问和处理HTML或XML文档的各个节点
标签的子节点和父节点
contents:获取Tag的所有子节点,返回一个list
print(bs.tag.contents) # 使用列表索引获取某一个元素 print(bs.tag.contents[1])
children:获取Tag的所有子节点,返回一个生成器
for child in tag.contents: print(child)
parent属性获取标签的父节点
parent_tag = tag.parent
标签的同级兄弟节点
可以使用.next_sibling和.previous_sibling属性获取标签的下一个或上一个同级兄弟节点。
next_sibling = tag.next_sibling
previous_sibling = tag.previous_sibling
递归遍历文档树
可以使用.find()和.find_all()方法在文档树中递归搜索匹配的标签。
可以使用.descendants生成器迭代器遍历文档树的所有子孙节点。
for tag in soup.find_all('a'):
print(tag)
for descendant in tag.descendants:
print(descendant)
遍历标签属性
可以使用.attrs属性获取标签的所有属性,并遍历它们。
for attr in tag.attrs:
print(attr)