Python-BeautifulSoup4 学习笔记

安装BeautifulSoup

# 安装bs4
# 官网地址 https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html#name
pip install beautifulsoup4
# 安装解析器 Python标准库自带Html解析器
pip install lxml
pip install html5lib

使用

实验网页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div style="height: 400px;background-color: whitesmoke;margin: 0 auto;">
        <h2 style="text-align: center;padding-top: 15px;">志研网</h2>
        <div style="margin: 0 auto;background-color: white;height: 200px;width: 500px;border: 1px solid rgb(172, 172, 172);">
            <h3 style="border-bottom: 1px solid  rgb(172, 172, 172);height: 40px;line-height: 40px;margin-top: 0;padding-left: 25px;">注册验证</h3>
            <p class="P1" id="S" style="margin-left: 25px;color:steelblue;">你好! yanggeol@qq.com</p>
            <p style="margin-left: 25px;color:steelblue;">欢迎注册志研网,请将注册码填到相应页面</p>
            <p style="margin-left: 25px;color:steelblue;">您的验证码是:965341</p>
            <p style="margin-left: 25px;color:gray;">@ginet.com</p>
        </div>
    </div>
</body>
</html>

基本使用

# 引入bs4
from bs4 import BeautifulSoup
# 打开index.html
soup = BeautifulSoup(open("index.html", encoding='UTF-8'))
# 获取标签<p></p>的内容  默认第一个
tag = soup.p
# 打印该标签
print(tag)
# 标签类型
print(type(tag))
# 标签名
print(tag.name)
# 修改名
tag.name = "blockquote"
print(tag)
# 打印标签的class名
print(tag['class'])
# 打印标签所有属性
print(tag.attrs)
# 打印标签的id
print(tag['id'])
# 删除属性
del tag['class']
del tag['id']

<p class="P1" id="S" style="margin-left: 25px;color:steelblue;">你好! yanggeol@qq.com</p>
<class 'bs4.element.Tag'>
p
<blockquote class="P1" id="S" style="margin-left: 25px;color:steelblue;">你好! yanggeol@qq.com</blockquote>
['P1']
{'class': ['P1'], 'id': 'S', 'style': 'margin-left: 25px;color:steelblue;'}
S

多值属性

# tag转换成字符串时,多值属性会合并为一个值
rel_soup = BeautifulSoup('<p>Back to the <a rel="index">homepage</a></p>')
rel_soup.a['rel']
# ['index']
rel_soup.a['rel'] = ['index', 'contents']
print(rel_soup.p)
# <p>Back to the <a rel="index contents">homepage</a></p>

# 转换的文档是XML格式,那么tag中不包含多值属性
xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml')
xml_soup.p['class']
# u'body strikeout'

打印标签的字符串

from bs4 import BeautifulSoup


soup = BeautifulSoup(open("index.html", encoding='UTF-8'))

tag = soup.p

print(tag.string)
# 你好! yanggeol@qq.com

# 不能编辑但可以替换字符串内容
tag.string.replace_with("No longer bold")

print(tag.string)

# tag包含了多个子节点,tag就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None 

遍历文档树

tag的属性

from bs4 import BeautifulSoup


soup = BeautifulSoup(open("index.html", encoding='UTF-8'))

# 打印head
print(soup.head)
# 打印标题
print(soup.title)
# 打印body下第一个p
print(soup.body.p)
# 获取当前第一个p
print(soup.p)
# 获取所有p
print(soup.find_all('p'))
# 将head的子节点以列表的方式输出
print(soup.head.contents)
print(soup.head.contents[0])

tag = soup.head
print(tag.contents[1].name)
# 通过tag的 .children 生成器,可以对tag的子节点进行循环
for child in tag.children:
    print(child)
# .descendants 属性可以对所有tag的子孙节点进行递归循环 包含字符串
for child in tag.descendants:
    print(child)

# tag中包含多个字符串,可以使用 .strings 来循环获取
for string in soup.strings:
    print(repr(string))
# 输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容
for string in soup.stripped_strings:
    print(repr(string))
# 全部是空格的行会被忽略掉,段首和段末的空白会被删除


节点

父节点

from bs4 import BeautifulSoup

soup = BeautifulSoup(open("index.html", encoding='UTF-8'))

tag = soup.h3

print(tag)
 # .parent 属性来获取某个元素的父节点
print(tag.parent)

# <h3>注册验证</h3>
# <div>
#   <h3>注册验证</h3>
# </div>


# BeautifulSoup 对象的 .parent 是None:

# 通过元素的 .parents 属性可以递归得到元素的所有父辈节点
for parent in tag.parents:
    if parent is None:
        print(parent)
    else:
        print(parent.name)

兄弟节点

# .next_sibling 和 .previous_sibling 属性来查询兄弟节点:
# 实际文档中的tag的 .next_sibling 和 .previous_sibling 属性通常是字符串或空白. 
from bs4 import BeautifulSoup

soup = BeautifulSoup(open("index.html", encoding='UTF-8'))

tag = soup.p
print(tag.previous_sibling.previous_sibling)
print(tag.next_sibling.next_sibling)

# 结果
# <h3 style="border-bottom: 1px solid  rgb(172, 172, 172);height: 40px;line-height: 40px;margin-top: 0;padding-left: 25px;">注册验证</h3>
# <p style="margin-left: 25px;color:steelblue;">欢迎注册志研网,请将注册码填到相应页面</p>

# .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出

回退和前进

# .next_element 属性指向解析过程中下一个被解析的对象(字符串或tag)
# .previous_element 属性刚好与 .next_element 相反,它指向当前被解析的对象的前一个解析对象
# 通过 .next_elements 和 .previous_elements 的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样

from bs4 import BeautifulSoup


soup = BeautifulSoup(open("index.html", encoding='UTF-8'))

tag = soup.p

print(tag.previous_element)
print(tag.next_elements)

过滤器

# 用于查找文档中所有的<b>标签
soup.find_all('b')

# 找出所有以b开头的标签,这表示<body>和<b>标签都应该被找到
import re
for tag in soup.find_all(re.compile("^b")):
    print(tag.name)
    
# 如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.
soup.find_all(["a", "b"])

# True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
for tag in soup.find_all(True):
    print(tag.name)

# 如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数,如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False
def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')
soup.find_all(has_class_but_no_id)

find_all

find_all(name, attrs,recursive,text, **kwargs)
# name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉.
soup.find_all("title")
# 如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.
# 搜索指定名字的属性时可以使用的参数值包括 字符串 , 正则表达式 , 列表, True .
# 使用多个指定名字的参数可以同时过滤tag的多个属性
soup.find_all(id='link2')
# 有些tag属性在搜索不能使用,比如HTML5中的 data-* 属性
# 但是可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag
data_soup.find_all(attrs={"data-foo": "value"})

# 通过 class_搜索CSS类名
# class_ 参数同样接受不同类型的 过滤器 ,字符串,正则表达式,方法或 True
soup.find_all("a", class_="sister")
# 搜索 class 属性时可以通过CSS值完全匹配
# 完全匹配 class 的值时,如果CSS类名的顺序与实际不符,将搜索不到结果

# 通过 text 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True
soup.find_all("a", text="Elsie")

# find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果.
soup.find_all("a", limit=2)

# 调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False
soup.html.find_all("title", recursive=False)

# find_all() 几乎是Beautiful Soup中最常用的搜索方法,所以我们定义了它的简写方法. BeautifulSoup 对象和 tag 对象可以被当作一个方法来使用,这个方法的执行结果与调用这个对象的 find_all() 方法相同,下面两行代码是等价的
soup.find_all("a")
soup("a")

find

find(name, attrs,recursive,text, **kwargs)
# 找寻一个满足条件的

find_parents 和 find_parent

find_all()find() 只搜索当前节点的所有子节点,孙子节点等.

find_parents()find_parent() 用来搜索当前节点的父辈节点,搜索方法与普通tag的搜索方法相同,搜索文档搜索文档包含的内容

find_next_siblings 和 find_next_sibling

find_next_siblings() 方法返回所有符合条件的后面的兄弟节点

find_next_sibling() 只返回符合条件的后面的第一个tag节点

find_previous_siblings 和 find_previous_sibling

find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点

find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点:

find_all_next 和 find_next

find_all_next() 方法返回所有符合条件的节点

find_next() 方法返回第一个符合条件的节点

find_all_previous 和 find_previous

find_all_next() 方法返回所有符合条件的节点

find_next() 方法返回第一个符合条件的节点

CSS选择器

# Beautiful Soup支持大部分的CSS选择器,在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数,即可使用CSS选择器的语法找到tag
soup.select("title")
# 通过tag标签逐层查找
soup.select("body a")
# 找到某个tag标签下的直接子标签
soup.select("head > title")
# 找到兄弟节点标签
soup.select("#link1 ~ .sister")
# 通过CSS的类名查找
soup.select(".sister")
soup.select("[class~=sister]")
# 通过tag的id查找
soup.select("#link1")
soup.select("a#link2")
# 通过是否存在某个属性来查找
soup.select('a[href]')
# 通过属性的值来查找
soup.select('a[href="http://example.com/elsie"]')

修改文档树

# 修改 .string
tag.string = "New link text."
# Tag.append() 方法想tag中添加内容,就好像Python的列表的 .append() 方法
soup = BeautifulSoup("<a>Foo</a>")
soup.a.append("Bar")
# 如果想添加一段文本内容到文档中也没问题,可以调用Python的 append() 方法或调用工厂方法 BeautifulSoup.new_string()
soup.new_string(" there")
# 如果想要创建一段注释,或 NavigableString 的任何子类,将子类作为 new_string() 方法的第二个参数传入
soup.new_string("Nice to see you.", Comment)
# 创建一个tag最好的方法是调用工厂方法 BeautifulSoup.new_tag()
soup.new_tag("a", href="http://www.example.com")
# Tag.insert() 方法与 Tag.append() 方法类似,区别是不会把新元素添加到父节点 .contents 属性的最后,而是把元素插入到指定的位置.与Python列表总的 .insert() 方法的用法下同
tag.insert(1, "but did not endorse ")
# insert_before() 方法在当前tag或文本节点前插入内容
soup.b.string.insert_before(tag)
# insert_after() 方法在当前tag或文本节点后插入内容
# Tag.clear() 方法移除当前tag的内容
tag.clear()
# PageElement.extract() 方法将当前tag移除文档树,并作为方法结果返回 方法实际上产生了2个文档树
markup = '<a href="http://example.com/">I linked to <i>example.com</i></a>'
soup = BeautifulSoup(markup)

a_tag = soup.a
i_tag = soup.i.extract()

a_tag
# <a href="http://example.com/">I linked to</a>
i_tag
# <i>example.com</i>

print(i_tag.parent)
None


# Tag.decompose() 方法将当前节点移除文档树并完全销毁
soup.i.decompose()
# PageElement.replace_with() 方法移除文档树中的某段内容,并用新tag或文本节点替代它
a_tag.i.replace_with(new_tag)
# PageElement.wrap() 方法可以对指定的tag元素进行包装,并返回包装后的结果
soup.p.string.wrap(soup.new_tag("b"))
# Tag.unwrap() 方法与 wrap() 方法相反.将移除tag内的所有tag标签,该方法常被用来进行标记的解包
a_tag.i.unwrap()

输出

# prettify() 方法将Beautiful Soup的文档树格式化后以Unicode编码输出,每个XML/HTML标签都独占一行
# BeautifulSoup 对象和它的tag节点都可以调用 prettify() 方法
soup.prettify()
soup.a.prettify()
# 如果只想得到结果字符串,不重视格式,那么可以对一个 BeautifulSoup 对象或 Tag 对象使用Python的 unicode() 或 str() 方法
# str() 方法返回UTF-8编码的字符串,可以指定编码的设置
str(soup)
unicode(soup.a)
# Beautiful Soup输出是会将HTML中的特殊字符转换成Unicode,

# 如果只想得到tag中包含的文本内容,那么可以用 get_text() 方法,这个方法获取到tag中包含的所有文版内容包括子孙tag中的内容,并将结果作为Unicode字符串返回
soup.get_text()
# 可以通过参数指定tag的文本内容的分隔符
soup.get_text("|")
# 可以去除获得文本内容的前后空白
soup.get_text("|", strip=True)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值