Beautiful Soup4数据解析与提取

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)

猜你喜欢

转载自blog.csdn.net/qq_38628046/article/details/129028890