一、简介
1、beautifulsoup是一个可以从html或者xml格式的文件中提取数据的python库。
2、安装:pip install beautifulsoup4
3、beautifulsoup支持python标准库中的<html>解析器,还支持一些第三方解析器,比如<lxml>,<html5lib>
①安装<lxml>:pip install lxml
②安装<html5lib>:pip install html5lib
二、准备html文档
from bs4 import BeautifulSoup html_doc = """ <html><head><title>The Dormouse's story</title></head> <body> <p id="my_p" class="title">hello<b id="bbb" class="boldest">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> """
三、生成bs对象
# 生成bs对象,传入html文档,选择解析器 soup = BeautifulSoup(html_doc, 'lxml') # 容错能力强,有时候文档不完整也能解析 print(soup.prettify())
四、遍历文档树
1、原理:直接通过标签名选择,选择速度快,但如果存在多个相同的标签则只返回第一个。
2、用法:
# 1、获取标签对象,第一个选择到的标签 p = soup.body.p # 2、获取标签名 print(p.name) # 3、获取标签的属性 # 三种方式效果一样 # class可能有多个,即便有一个也放到列表中 print(p.attrs.get('class')) print(p['class']) print(p.get('class')) # 4、获取标签的内容 # 标签内部所有的文本拼到一起 print(p.text) # 标签内部为纯文本时返回该文本,若非纯文本,比如有子标签的情况,返回None print(p.string) # 获得一个生成器,存储着标签内部所有内容,包括文本和子标签 print(p.strings) # 5、嵌套选择,可以跳级获取内部子标签 a = soup.body.a # 6、子节点、子孙节点 # 获取所有子节点,包括跳级的 print(soup.p.contents) # contents的结果放入迭代器中 print(soup.p.children) # 7、父节点、祖先节点 # 最亲的父标签 print(soup.a.parent) # 所有有子标签的标签 print(soup.a.parents) # 找到a标签所有的祖先节点,父亲的父亲,父亲的父亲的父亲... # 8、兄弟节点 # 下一个兄弟 print(soup.a.next_sibling) # 上一个兄弟 print(soup.a.previous_sibling) # 后面的所有兄弟放放入迭代器 print(soup.a.next_siblings) # 前面的所有兄弟放放入迭代器 print(soup.a.previous_siblings)
五、搜索文档树
1、基本方法:
①find:只返回找到的第一个。
②find_all:找到所有。
2、五种过滤器:
①字符串过滤 --- 过滤内容是字符串:
a = soup.find(name='a') res1 = soup.find(id='my_p') # class是python关键字,所有替换为class_ res2 = soup.find(class_='story') res3 = soup.find(href='http://example.com/elsie') res4 = soup.find(attrs={'id': 'my_p'}) res5 = soup.find(attrs={'class': 'story'})
②正则匹配式:
import re re_1 = re.compile('^b') re_2 = re.compile('^l') res1 = soup.find(name=re_1) res2 = soup.find_all(id=re_2)
③列表:
res1 = soup.find_all(name=['body', 'b']) res2 = soup.find_all(class_=['sister', 'title'])
④布尔:
res1 = soup.find_all(name=True) res2 = soup.find_all(id=True) res3 = soup.find_all(id=False) res4 = soup.find_all(href=True)
⑤方法:
def has_class_but_no_id(tag): return tag.has_attr('class') and not tag.has_attr('id') res = soup.find_all(has_class_but_no_id)
3、其他方法:
# 限制查找的条数 res1 = soup.find_all(name=True, limit=1) # recursive默认True,递归查找,找子子孙孙,改为False,则只找儿子 res2 = soup.body.find_all(name='p', recursive=False) res3 = soup.body.find_all(name='b', recursive=True)
4、css方式选择:
# id选择器 res1 = soup.select('#my_p') # 所有子孙 res2 = soup.select('body p') # 只是儿子 res3 = soup.select('body>p') res4 = soup.select('body>p')[0].text # 直接子节点(儿子) # 获得的标签对象可以继续用标签对象的方法 res5 = soup.select('body>p')[0].a.find()
六、bs还可以用于修改文档树,比如修改xml格式的配置文件