BeautifulSoup解析库
解析库
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(html, 'html.parser') | 速度适中,容错能力强 | 老版本python容错能力差 |
lxml HTML解析库 | BeautifulSoup(html, 'lxml') | 速度快,容错能力强 | 安装c语言库 |
lxml XML解析库 | BeautifulSoup(html, 'xml') | 速度快,唯一支持XML的解析器 | 安装c语言库 |
html5lib | BeautifulSoup(html, 'html5lib') | 最高的容错性,浏览器方式解析文档,生成HTML格式文档 | 速度慢 |
基本使用
from bs4 import BeautifulSoup
html = '''
<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, 'lxml')
print(soup.prettify())
选择标签
soup = BeautifulSoup(html, 'lxml')
print(soup.title) # <title>The Dormouse's story</title>
print(type(soup.title)) # <class 'bs4.element.Tag'>
print(soup.head) # <head><title>The Dormouse's story</title></head>
print(soup.p) # <p class="title"><b>The Dormouse's story</b></p>
可以看到,当有多个标签满足条件时,只返回了第一个。
获取标签名称(.name)
soup = BeautifulSoup(html, 'lxml')
print(soup.title.name) # title
获取属性(.attrs)
HTML 4定义了一系列可以包含多个值的属性.在HTML5中移除了一些,却增加更多.最常见的多值的属性是 class (一个tag可以有多个CSS的class). 还有一些属性 rel , rev , accept-charset , headers , accesskey . 在Beautiful Soup中多值属性的返回类型是list:
如果某个属性看起来好像有多个值,但在任何版本的HTML定义中都没有被定义为多值属性,那么Beautiful Soup会将这个属性作为字符串返回
如果转换的文档是XML格式,那么tag中不包含多值属性
soup = BeautifulSoup(html, 'lxml')
print(soup.p.attrs['class']) # ['title']
print(soup.p['class']) # ['title']
print(soup.a.attrs['id']) # link1
以上两种方法都是可以实现的。
获取内容(.string/.strings)
soup = BeautifulSoup(html, 'lxml')
print(soup.p.string) # The Dormouse's story
嵌套选择
soup = BeautifulSoup(html, 'lxml')
# 获取head标签里面的title标签的内容
print(soup.head.title.string) # The Dormouse's story
子节点和子孙节点
contents以一个列表的形式返回所有的子节点
soup = BeautifulSoup(html, 'lxml')
# 将p标签下面的所有的子节点以列表的形式返回
print(soup.p.contents) # [<b>The Dormouse's story</b>]
children以一个迭代器的形式返回所有的子节点
soup = BeautifulSoup(html, 'lxml')
# 返回的是一个列表迭代器
print(soup.p.children) # <list_iterator object at 0x000002174E8C8128>
for i,child in enumerate(soup.p.children):
print(i,child) # 0 <b>The Dormouse's story</b>
descendants以一个迭代器的形式返回所有的子孙节点
soup = BeautifulSoup(html, 'lxml')
print(soup.p.descendants) # <generator object descendants at 0x000002A2AD9E86D0>
for i,child in enumerate(soup.p.descendants):
print(i,child)
# 0 <b>The Dormouse's story</b>
# 1 The Dormouse's story
父节点和祖先节点
parent来获取父节点
soup = BeautifulSoup(html, 'lxml')
print(soup.b.parent) # <p class="title"><b>The Dormouse's story</b></p>
parents来获取祖先节点,是一个迭代器的形式
soup = BeautifulSoup(html, 'lxml')
print(list(soup.b.parents))
兄弟节点
next_siblings获取后面的全部的兄弟节点,返回一个列表
soup = BeautifulSoup(html, 'lxml')
print(list(soup.p.next_siblings))
previous_siblings获取前面的全部的兄弟节点,返回一个列表
soup = BeautifulSoup(html, 'lxml')
print(list(soup.p.previous_siblings))
find_all()
find_all( name , attrs , recursive , text , **kwargs )
bs4中最常用的方法,find_all()方法返回满足条件的全部标签,find()方法只返回第一个标签。
返回结果是一个列表,每一个元素都是一个tag对象,可以使用get_text()来获取标签的文本。
- name 参数
可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.
soup.find_all("title")
# [<title>The Dormouse's story</title>]
- keyword 参数
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索
搜索指定名字的属性时可以使用的参数值包括 字符串 , 正则表达式 , 列表, True .
为True时,相当于选取全部的带有该属性的标签,不论属性值是多少。
soup.find_all(id='link2')
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
soup.find_all(href=re.compile("elsie"))
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
- attrs 参数
有些tag属性在搜索不能使用,比如HTML5中的 data-* 属性, 这时候使用attrs参数定义一个字典参数来搜索包含特殊属性的tag:
data_soup.find_all(attrs={"data-foo": "value"})
# [<div data-foo="value">foo!</div>]
- text参数
通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True .
soup.find_all(text='foo')
soup.find_all("a", text="Elsie")
- limit 参数
使用 limit 参数限制返回结果的数量
soup.find_all("a", limit=2)
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
- recursive 参数
调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False
soup.html.find_all("title", recursive=False)
CSS选择器
通过select()直接传入CSS选择器即可
soup.select("title")
# [<title>The Dormouse's story</title>]
soup.select("p nth-of-type(3)")
# [<p class="story">...</p>]