BeautifulSoup介绍

BeautifulSoup是一个用于从HTML和XML文件中提取数据的Python库。它将自动将输入的文档转换为Unicode编码,输出文档转换为UTF-8编码。其主要功能有:

  • 导航
  • 搜索
  • 修改分析树

Warning: 注意

一般情况下不需要考虑编码方式,除非文档没有指定一个编码方式,因此遇到BeautifulSoup不能自动识别编码方式的情况,只需要说明一下原始编码方式即可。

环境准备

Windows使用前需要安装库,终端指令如下:

pip install beautifulsoup4

Info: 源码方式安装

  1. 打开源码地址进行下载:点击访问源码地址
  2. 使用控制台打开进入源码所在路径
  3. 执行命令:python setup.py install

适配解释器

BeautifulSoup支持python标准库中包含的HTML解析器,但常用的有lxml解析器和html5lib解析器,可以通过下列命令进行安装解析器(安装其一即可):

pip install lxml
pip install html5lib

BeautifulSoup的使用

导包

from bs4 import BeautifulSoup

创建BeautifulSoup对象

# 创建BeautifulSoup对象并指定解析器为lxml
soup = BeautifulSoup(html_doc,features='lxml')

html_doc:为HTML的字符串 features:用于指定解析器

Tips:

若HTML为'index.html'类型的文件,则可以将原来的html_doc替换为open('index.html')即可。

BeautifulSoup对象的prettify()方法可以对输出的内容自动进行格式化排版,按HTML层级添加缩进和换行,结构清晰。

获取节点内容

获取节点对应的代码语法格式如下:

soup.标签         # 获取节点对应的代码
soup.标签.name    # 获取节点对应的名称

示例:

soup = BeautifulSoup(html_doc,features="lxml")
print(soup.head)      # 打印head节点
print(soup.body)      # 打印body节点
print(soup.title)     # 打印title节点
print(soup.p.name)    # 打印p节点的名称

Warning: 注意

该获取方法仅打印第一个检测到的<p>标签而忽略其他。

获取节点属性

若已选择一个指定的节点名称,那么只需调用attrs即可获取这个节点下的所有属性,返回值为字典类型。语法格式如下:

soup.标签.attrs           # 获取指定节点的属性
soup.标签.attrs[属性名]    # 获取指定节点的指定属性名的值(attrs可省略)

示例:

soup = BeautifulSoup(html_doc,features="lxml")
print(soup.meta.attrs)         # 打印meta的属性
print(soup.link.attrs)         # 打印link的属性
print(soup.div.attrs['id'])    # 打印div的id属性值
print(soup.div['id'])          # 打印div的id属性值

获取节点包含的文本内容

若要获取节点包含的文本内容,只需在节点名称后面添加string属性即可。语法如下:

soup.标签.string     # 获取指定节点的文本内容

示例:

soup = BeautifulSoup(html_doc,features="lxml")
print(soup.title.string)        # 打印title节点包含的文本内容
print(soup.link.string)         # 打印link节点包含的文本内容

嵌套获取节点内容

使用beautifulsoup获取每个节点的内容时,可以通过 . 直接获取下一个节点的内容,代码如下:

soup = BeautifulSoup(html_doc,features="lxml")
print(soup.head.title)         # 打印head节点中title节点内容
print(soup.head.title.string)  # 打印head节点中title节点的文本内容
print(soup.div.attrs['id'])    # 打印div的id属性值
print(soup.div['id'])          # 打印div的id属性值

Info: 说明

获取head与其内部的title节点内容时数据类型均为 <class 'bs4.element.Tag'>,说明在Tag类的基础上可以获取当前节点的子节点内容

关联获取

先确认某一节点,然后以该节点为中心获取对应的子节点、孙节点、父节点及兄弟节点。

获取子节点

获取某节点下面的所有的子节点时,可以使用 contentschildren 属性来实现,其中contents返回一个列表,该列表中每个元素都是一个子节点内容,而children所返回的则是一个list_iterator类型的可迭代对象,需要转换成list类型或遍历进行获取。语法如下:

soup = BeautifulSoup(html_doc,features="lxml")
print(soup.head.contents)         # 列表形式打印head节点下所有子节点
print(soup.head.children)         # 可迭代对象形式打印head节点下所有子节点

获得孙节点

在获取某节点下所有的子孙节点时,可以使用 descendants 属性来实现,该属性会返回一个generator对象,其内容需要转换成list类型或遍历进行获取。语法如下:

soup = BeautifulSoup(html_doc,features="lxml")
# 打印body节点下所欲子孙节点内容的generator对象
print(soup.body.descendants)

获取父节点

获取父节点存在两种方式:

  1. 通过 parents 属性直接获取指定节点的父节点内容,还可以返回父节点及以上节点(祖先节点)内容,其内容需要转换成list类型或遍历进行获取。语法如下:
soup = BeautifulSoup(html_doc,features='lxml')
print(soup.title.parent)  # 打印title节点的父节点内容
print(soup.title.parents) # 打印title节点的父节点及以上内容的generator对象

Info: 说明

parents属性所获取父节点的顺序为head、html、document,此处的 [document] 表示文档对象,时整个HTML文档,也是BeautifulSoup对象。

获取兄弟节点

假若在一段HTML中获取第一个p节点的下一个div兄弟节点时可以使用 next_sibling 属性,若要获取当前div节点的上一个兄弟节点p时,则可以使用 previous_sibling 属性。想获取当前节点后面的所有兄弟节点,则可以使用 next_siblings 属性,若要获取前面的,则使用 previous_siblings 属性。这两个属性都将以generator对象的形式返回,语法格式如下:

soup = BeautifulSoup(html_doc,features='lxml')
print(soup.p.next_sibling)  # 打印第一个p节点的下一个兄弟节点
# 打印p节点前面的所有兄弟节点的generator对象
print(soup.p.previous_siblings)

方法获取内容

  • find_all()
  • find()

find_all()获取所有符合条件的内容,find()获取第一个匹配的节点内容,接下来以find_all()为例进行整理:

find_all(name=None,attrs={},recursive=True,text=None,limit=None,**kwargs)

name参数

用来指定节点名称,指定该参数以后将返回一个可迭代对象,所有符合条件的均为对象的一个元素。代码如下:

print(soup.find_all(name='p')) # 打印所有名称为p的节点内容

Info: 说明

bs4.element.ResultSet类型的数据与python的列表类型,可以使用切片的方式进行数据获取,如:print(soup.find_all(name='p')[0])

Warning: 嵌套获取

因为bs4.element.ResultSet数据中的每一个元素都是bs4.element.Tag类型,所以可以直接对某一元素进行嵌套获取,代码如下:

print(soup.find_all(name='p')[0])
print(soup.find_all(name='p')[0].find_all(name='a'))

attrs参数

在填写attrs参数时,默认情况下需要填写字典类型的参数值,不过也可以通过以赋值的方式填写参数。代码如下:

print(soup.find_all(attrs={'values':'1'}))
print(soup.find_all(value='1')) # 打印value值为1的所有内容

text参数

指定text参数可以获取节点中的文本,该参数可以指定字符串或者正则表达式对象,代码如下:

print(soup.find_all(text="Python"))
print(soup.find_all(text=re.compile('Python')))

CSS选择器

参考文档:点击进行访问

若是Tag或BeautifulSoup对象都可以直接调用 select() 方法,然后填写指定参数即可通过CSS选择器获取节点中的内容。

print(soup.select('p'))       # 打印所有p节点内容
print(soup.select('p')[0])    # 打印所有p节点中的第一个节点
print(soup.select('html head title')) # 打印逐层获取的title节点
print(soup.select('.test_2'))   # 打印类名为test_2所对应的节点
print(soup.select('#class_1'))  # 打印id值为class_1所对应的节点

select_one()方法:用于获取所有符合条件节点中的第一个节点。