这一篇文章接在上一篇 基础学习——BeautifulSoup篇(1) 之后,今天来继续学习BeautifulSoup
欢迎关注公众号:老白和他的爬虫
4.遍历文档树
4.7父节点和兄弟节点
父节点可以通过.parent
和.parents
操作得倒
from bs4 import BeautifulSoup
if __name__ == "__main__":
html_doc = """
The Dormouse's story
The Dormouse's story
Once upon a time there were three little sisters; and their names were
Elsie,
Lacie and
Tillie;
and they lived at the bottom of a well.
...
"""
soup = BeautifulSoup(html_doc,'lxml')
head_tag = soup.head
title_tag = head_tag.contents[0]
print(title_tag.parent) #打印title_tag的父节点
link = soup.a
for parent in link.parents: #循环打印a标签的父节点
if parent is None:
print(parent)
else:
print(parent.name)
兄弟节点些微有点不同,一个节点可以通过.next_sibling
和 .previous_sibling
得到它之前和之后的兄弟节点,同样,也可以通过.next_siblings
和 .previous_siblings
遍历操作得倒所有的兄弟节点。
4.8回退和缩进
上一个内容讲的.next_sibling
和 .previous_sibling
其实就已经有了缩进和回退的味道了,但是他们是不同的。我们使用解析器把html文档解析成了一个又一个事件或者说是标签,兄弟节点只能在这一级进行前后操作,然而要对整个文档进行操作,我们就必须使用到.next_element
和 .previous_element
。我们用上面的文档树来举一个例子
last_a_tag = soup.find("a", id="link2")
print(last_a_tag.next_sibling)
print(last_a_tag.next_element)
print(last_a_tag.next_sibling)
的输出结果是and
因为第二个下一个兄弟节点是
and
,但是print(last_a_tag.next_element)
的输出结果是Lacie
,因为第二个下一个元素是比它低一级的字符串
Lacie
。这段代码理解的画,这两个操作也很好理解了,同理它还有.next_elements
和 .previous_elements
这两个操作,具体怎么用不用我说了吧,类比一下就会了。
4.9. find_all()
find_all(name , attrs , text , keyword )
使用.find_all()
操作可以设置这些常用参数
4.9.1 name参数
.find_all()
可以直接查找tag的name来找到对应的标签
soup.find_all('b') #用来查找所有的标签
4.9.2 keyword参数.find_all()``.find_all()
print(soup.find_all(id='link2')) #用来查找id为link2的标签
.find_all()
操作可以与正则表达式搭配,个人认为这一步在查找一些特定标签时十分有用
import re
#找到所有标签中以b开头的标签
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
#提取所有a标签中包含字符串example的链接
for x in soup.find_all('a',href = re.compile('example')):
print(x.get('href'))
这里记住一点,.find_all()
内部的多个参数是可以同时写的,上面这段代码我这样写也可以
for x in soup.find_all(class_ = 'sister' ,href = re.compile('example')):
print(x.get('href'))
class
应该是python的关键字,所以我们这里需要用class_
来表示class
4.9.3 attrs参数
可以通过 find_all()
方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag
data_soup = BeautifulSoup('foo!','lxml')
print(data_soup.find_all(attrs={"data-foo": "value"}))
4.9.4 text参数
print(soup.find_all(text="Elsie")) #输出文本为Elsie的字符串
print(soup.find_all(text=["Tillie", "Elsie", "Lacie"])) #输出文本为列表中所包含的字符串
print(soup.find_all(text=re.compile("Dormouse"))) #输出文本包含Dormouse的字符串
4.9.5 limit参数
limit参数可以限制返回节点的数量
print(soup.find_all('a',limit = 2)) #本身可以返回三个a标签,但是由于limit限制只返回两个
4.10 find()
.find()
其实就是.find_all()
加上了limit = 1
的操作,区别于.find()
返回的是结果,.find_all()
返回的是集合
.find()
和.find_all()
还有其他的一些操作,这里就不一一举例了,避免这个教程太过繁琐,只要熟练的掌握.find()
和.find_all()
,就已经能解决很多的问题。其他的一些操作包括
find_parents(),find_parent(),find_next_siblings(),find_next_sibling(),find_previous_siblings(),find_previous_sibling(),find_all_next(),find_next(),find_all_previous(),find_previous()
4.11 CSS选择器
这一个功能我不打算在这里说,因为这里能实现的功能在前面我们都已经实现了,只不过更熟悉css的人可以选择这种方法。
5.修改文档树
给tag的 .string
属性赋值,就相当于用当前的内容替代了原来的内容:
markup = 'I linked to example.com'
soup = BeautifulSoup(markup,'lxml')
tag = soup.a
tag.string = "New link text."
print(tag)
使用.append()
方法可以像标签添加内容
markup = 'I linked to '
soup = BeautifulSoup(markup,'lxml')
tag = soup.a
print(tag)
tag.append("haha")
print(tag)
如果想要创建一段注释
from bs4 import Comment
new_comment = soup.new_string("Nice to see you.", Comment)
tag.append(new_comment)
print(tag)
如果想要创建一个新的tag
soup = BeautifulSoup("",'lxml')
original_tag = soup.b
new_tag = soup.new_tag("a", href="http://www.example.com")
original_tag.append(new_tag)
print(original_tag)
new_tag.string = "Link text."
print(original_tag)
使用'.insert()'插入具体的内容
markup = 'I linked to example.com'
soup = BeautifulSoup(markup,'lxml')
tag = soup.a
tag.insert(1, "but did not endorse ") #参数1控制插入字符串的位置
print(tag)
移除当前tag的内容
tag.clear()
print(tag)
移除当前的tag节点
a_tag = soup.a
i_tag = soup.i.extract()
print(a_tag)
print(i_tag)
使用decompose()
完全销毁当前tag节点
markup = 'I linked to example.com'
soup = BeautifulSoup(markup,'lxml')
tag = soup.a
a_tag = soup.a
soup.i.decompose()
print(a_tag)
使用replace_with()
替换节点
markup = 'I linked to example.com'
soup = BeautifulSoup(markup,'lxml')
tag = soup.a
a_tag = soup.a
new_tag = soup.new_tag("b")
new_tag.string = "example.net"
a_tag.i.replace_with(new_tag)
print(tag)
6.输出
.prettify()
方法将BeautifulSoup的文档树格式化后以Unicode编码输出,每个XML/HTML标签都独占一行
markup = 'I linked to example.com'
soup = BeautifulSoup(markup,'lxml')
print(soup.prettify())
如果不想格式化输出,可以选择压缩输出
print(str(soup))
如果只想得到标签中的文本内容
markup = '\nI linked to example.com\n'
soup = BeautifulSoup(markup,'lxml')
print(soup.get_text())
print(soup.get_text("|")) #指定文本分隔符
print(soup.get_text("|", strip=True)) #去除文本内容前后空白
好了,BeautifulSoup的基础知识我们已经学习完毕了,你可以跟着这两篇文章来学习掌握BeautifulSoup,也可以选择把这两篇当作字典,当你在写爬虫时来翻阅