了解Beautiful Soup
Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式
安装
-
beautifulsoup4
>: pip install beautifulsoup4
-
解析器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml .根据操作系统不同,可以选择下列方法来安装lxml:
$ apt-get install Python-lxml
$ easy_install lxml
$ pip install lxml
另一个可供选择的解析器是纯Python实现的 html5lib , html5lib的解析方式与浏览器相同,可以选择下列方法来安装html5lib:
$ apt-get install Python-html5lib
$ easy_install html5lib
$ pip install html5lib
下表列出了主要的解析器,以及它们的优缺点,官网推荐使用lxml作为解析器,因为效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib, 因为那些Python版本的标准库中内置的HTML解析方法不够稳定.
| 解析器 | 使用方法 | 优势 | 劣势 |
|---|---|---|---|
| Python标准库 | BeautifulSoup(markup, "html.parser") |
|
|
| lxml HTML 解析器 | BeautifulSoup(markup, "lxml") |
|
|
| lxml XML 解析器 |
BeautifulSoup(markup, ["lxml", "xml"]) BeautifulSoup(markup, "xml") |
|
|
| html5lib | BeautifulSoup(markup, "html5lib") |
|
|
案例目标页面代码
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>
"""
from bs4 import BeautifulSoup # 实例化BeautifulSoup, 将目标页面代码和解析器传入 soup = BeautifulSoup(html_doc, "lxml") # 使用lxml解析器,,容错率高
基础使用
from bs4 import BeautifulSoupsoup = BeautifulSoup(html_doc, "lxml")
res = soup.prettify() # 美化页面代码
print(res)
遍历文档树
接通过标签名字选择,特点是选择速度快,但如果存在多个相同的标签则只返回第一个
#1、用法 #2、获取标签的名称 #3、获取标签的属性 #4、获取标签的内容 #5、嵌套选择 #6、子节点、子孙节点 #7、父节点、祖先节点 #8、兄弟节点
from bs4 import BeautifulSoupsoup = BeautifulSoup(html_doc, "lxml")
# soup = BeautifulSoup(open('a.html'), 'lxml')# 1.用法
存在多个相同的标签则只返回第一个
print(soup.p) # <p class="title"><b>The Dormouse's story</b></p>
# 2、获取标签的名称
print(soup.p.name) # p# 3、获取标签的属性
print(soup.p.attrs) # {'class': ['title']}# 4、获取标签的内容
p内的文本只有一个时,取到,否则为None
print(soup.p.string) # The Dormouse's story
拿到一个生成器对象, 取到p下所有的文本内容
print(soup.p.strings) # <generator object _all_strings at 0x0000023916778938>
取到p下所有的文本内容
print(soup.p.text)
# 去掉空白
for line in soup.stripped_strings:
print(line)'''
如果tag包含了多个子节点,tag就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None,如果只有一个子节点那么就输出该子节点的文本,比如下面的这种结构,soup.p.string 返回为None,但soup.p.strings就可以找到所有文本
<p id='list-1'>
哈哈哈哈
<a class='sss'>
<span>
<h1>aaaa</h1>
</span>
</a>
<b>bbbbb</b>
</p>
'''# 5、嵌套选择
head标签内的title标签内的文本
print(soup.head.title.string) # The Dormouse's story
body标签内的a标签内的文本
print(soup.body.a.string) # Elsie
# 6、子节点、子孙节点
p下所有子节点
print(soup.p.contents) # [<b>The Dormouse's story</b>]
包含p下所有子节点
print(soup.p.children) # <list_iterator object at 0x000001FD5E4DF320>
for i, child in enumerate(soup.p.children):
print(i, child) # 0 <b>The Dormouse's story</b>获取子孙节点,p下所有的标签都会选择出来
print(soup.p.descendants) #
for i, child in enumerate(soup.p.descendants):
print(i, child)# 7、父节点、祖先节点
获取a标签的父节点
print(soup.a.parent)
# 找到a标签所有的祖先节点,父亲的父亲,父亲的父亲的父亲...
print(soup.a.parents)# 8、兄弟节点
print(soup.a.next_sibling) # 下一个兄弟
print(soup.a.previous_sibling) # 上一个兄弟print(list(soup.a.next_siblings)) # 下面的兄弟们=>生成器对象
print(soup.a.previous_siblings) # 上面的兄弟们=>生成器对象