目录

一.bs4简介

1.基本概念

2.源码分析

二.bs4的使用

1.快速开始

2.bs4的对象种类

三.遍历文档树 遍历子节点

1.contents      children      descendants
2.string      strings      stripped_strings

四.遍历文档树 遍历父节点

1.parent和parents

五.遍历文档树 遍历兄弟节点

六.搜索树

七.find_all() 和 find()

八.select()方法

九.修改文档树


一.bs4简介

1.基本概念

Beautiful Soup 是一个可以从HTML或XML文件中提取数据的网页信息提取库。

2.源码分析

(1)中文官方解释文档:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/

python写bs系统 python bs4教程_python写bs系统

https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/

(2)安装:pip install lxml

pip install bs4

二.bs4的使用

1.快速开始

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>
"""
# soup = BeautifulSoup(html_doc, features="lxml")
soup = BeautifulSoup(html_doc, "lxml")
# prettify() 把要解析的字符串以标准的缩进格式输出
# print(soup.prettify())
# print(soup.title)   #<title>The Dormouse's story</title>
# string获取文本内容的
# print(soup.title.string)    #The Dormouse's story
# name获取标签名
# print(soup.title.name)  #title


# 需求获取所有p标签
# print(soup.p)   #获取第一个
# tag = soup.find_all('p')
# # print(soup.find_all('p'))   #获取所有p标签,以列表返回
# print(len(tag))
# for i in tag:
#     print(i)

# 获取a标签的属性href
tag = soup.find_all('a')
for i in tag:
    # print(i.get('href'))   #1.get方法里面将属性名以字符串传进去

    # print(i.attrs)  #2.将属性各个放在字典中返回
    # print(i.attrs['href'])

    print(i['href'])  #直接对i取href

2.bs4的对象种类

(1)tag:标签

(2)NavigableString:可导航的字符串

(3)BeautifulSoup:bs对象

(4)Comment:注释

from bs4 import BeautifulSoup

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>

<span><!--我是一个注释--></span>

<p class="story">...</p>
"""

soup = BeautifulSoup(html_doc, 'lxml')
# print(type(soup.title))  #<class 'bs4.element.Tag'>
# print(type(soup.title.string))    #<class 'bs4.element.NavigableString'>
# print(type(soup))       #<class 'bs4.BeautifulSoup'>

print(type(soup.span.string))       #<class 'bs4.element.Comment'>

三.遍历文档树 遍历子节点

bs里面有三种情况,第一个是遍历,第二个是查找,第三个是修改。

1.contents      children      descendants

(1)contents返回的是一个所有子节点的列表;

(2)children返回的是一个子节点的迭代器;

(3)descendants返回的是一个生成器遍历子子孙孙。

from bs4 import BeautifulSoup

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>

<span><!--我是一个注释--></span>

<p class="story">...</p>
"""
'''
遍历子节点
contents 返回的是一个所有子节点的列表
children 返回的是一个子节点的迭代器
descendants 返回的是一个生成器遍历子子孙孙
'''
soup = BeautifulSoup(html_doc, 'lxml')
heads = soup.head
# print(heads.contents)

# print(heads.children)
# for head in heads.children:
#     print(head)

# html = soup.html
# # for i in html.contents:
# #     print(i)
# for i in html.descendants:     #子子孙孙
#     print(i)

2.string      strings      stripped_strings

(1)string获取标签里面的内容;

(2)strings返回的是一个生成器对象。用来获取多个标签内容;

(3)stripped_strings和strings基本一致,但是它可以把多余的空格去掉;

(在一些情况下,可以将生成器强转为列表,方便使用)

'''
string 获取标签里面的内容
strings 返回的是一个生成器对象用过来获取多个标签内容
stripped_strings 和strings基本一致 但是它可以把多余空格去掉
'''
# title_tag = soup.title
# print(title_tag.string)

# html_tag = soup.html
# print(html_tag.strings)
# for i in html_tag.strings:
#     print(i)

# html_tag = soup.html
# print(html_tag.stripped_strings)
# for i in html_tag.stripped_strings:
#     print(i)

四.遍历文档树 遍历父节点

1.parent和parents

(1)parent直接获得父节点;

(2)parents获取所有的父节点,以生成器返回;

'''
遍历父节点
parent直接获得父节点
parents获取所有的父节点,以生成器返回
'''
# t = soup.title
# print(t.parent)
#
# html = soup.html
# print(html.parent)
# print(type(html.parent))  #<class 'bs4.BeautifulSoup'>
#
# print(t.parents)
# for i in t.parents:
#     print(i)
#     print("*"*50)



五.遍历文档树 遍历兄弟节点

(1)next_sibling        下一个兄弟节点;

(2)previous_sibling        上一个兄弟节点;

(3)next_siblings        下一个所有兄弟节点;

(4)previous_siblings        上一个所有兄弟节点;

'''
遍历兄弟节点
next_sibling 下一个兄弟节点
previous_sibling  上一个兄弟节点
next_siblings   下一个所有兄弟节点
previous_siblings 上一个所有兄弟节点
'''
html2 = """ 
<html>
    <head>
        <title>The Dormouse's story</title> 
    </head> 
    <body>
        <p class="story">p1</p>
        <span class="story">span</span>
        <p class="story">p2</p> 
    </body> 
</html> 
"""
# soup2 = BeautifulSoup(html2, 'lxml')
# s = soup2.span
# print(s.previous_sibling)  #空白或换行也会是被视作一个节点,所以是空的
# for i in s.previous_siblings:
#     print(i)

六.搜索树

(1)字符串过滤器;

(2)正则表达式过滤器:

我们用正则表达式里面的compile方法编译一个正则表达式传给一个find或者findall这个方法可以实现一个正则表达式的一个过滤器搜索;

(3)列表过滤器;

(4)True过滤器;

from bs4 import BeautifulSoup
# find()
# find_all()
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>

<span><!--我是一个注释--></span>

<p class="story">...</p>
"""
# 字符串过滤器
soup = BeautifulSoup(html_doc, 'lxml')
# find()
# 返回符合条件第一个结果
# result = soup.find('a')
# print(result)

# find_all()   以列表形式返回所有符合规则的
# result = soup.find_all('a')
# print(result)

# 列表过滤器
# result = soup.find_all(['title','b'])
# print(result)

七.find_all() 和 find()

1.find_all()方法以列表形式返回所有的搜索到的标签数据;

2.find()方法返回搜索到的第一条数据;

3.find_all()方法参数:

def find_all(self, name=None, attrs={}, recursive=True, text=None,
                 limit=None, **kwargs):

(1)name:tag名称;

(2)attrs:标签的属性;

(3)recursive:是否递归搜索;

(4)text:文本内容;

(5)limit:限制返回个数;

(6)kwargs:关键字参数;

html = """
<table class="tablelist" cellpadding="0" cellspacing="0">
    <tbody>
        <tr class="h">
            <td class="l" width="374">职位名称</td>
            <td>职位类别</td>
            <td>人数</td>
            <td>地点</td>
            <td>发布时间</td>
        </tr>
        <tr class="even">
            <td class="l square"><a target="_blank" href="position_detail.php?id=33824&keywords=python&tid=87&lid=2218">22989-金融云区块链高级研发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-25</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=29938&keywords=python&tid=87&lid=2218">22989-金融云高级后台开发</a></td>
            <td>技术类</td>
            <td>2</td>
            <td>深圳</td>
            <td>2017-11-25</td>
        </tr>
        <tr class="even">
            <td class="l square"><a target="_blank" href="position_detail.php?id=31236&keywords=python&tid=87&lid=2218">SNG16-腾讯音乐运营开发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>2</td>
            <td>深圳</td>
            <td>2017-11-25</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=31235&keywords=python&tid=87&lid=2218">SNG16-腾讯音乐业务运维工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-25</td>
        </tr>
        <tr class="even">
            <td class="l square"><a target="_blank" href="position_detail.php?id=34531&keywords=python&tid=87&lid=2218">TEG03-高级研发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=34532&keywords=python&tid=87&lid=2218">TEG03-高级图像算法研发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="even">
            <td class="l square"><a target="_blank" href="position_detail.php?id=31648&keywords=python&tid=87&lid=2218">TEG11-高级AI开发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>4</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=32218&keywords=python&tid=87&lid=2218">15851-后台开发工程师</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="even">
            <td class="l square"><a target="_blank" href="position_detail.php?id=32217&keywords=python&tid=87&lid=2218">15851-后台开发工程师</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a id="test" class="test" target='_blank' href="position_detail.php?id=34511&keywords=python&tid=87&lid=2218">SNG11-高级业务运维工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
    </tbody>
</table>
"""
soup2 = BeautifulSoup(html, 'lxml')

# 获取所有的tr标签
# trs = soup2.find_all('tr')
# for t in trs:
#     print(t)
#     print('*'*50)

# 获取第三个tr标签 用列表下标索引取值 从0开始的
# trs = soup2.find_all('tr')
# print(trs[2])

# 通过属性值定位标签 找class="even"的tr标签
# trs = soup2.find_all('tr', attrs={'class': 'even'})
# for t in trs:
#     print(t)
#     print('*'*50)

# 注意:class后面一定要有下划线
# trs = soup2.find_all('tr', class_="even")
# for t in trs:
#     print(t)
#     print('*'*50)


# 获取到  class="even"并且id="test" 的tr标签  可以设置提取数量使用参数 limit = 数量
# trs = soup2.find_all('tr', class_="even", id="test")
# for t in trs:
#     print(t)
#     print('*'*50)

# 获取属性值
# a_tags = soup2.find_all('a')
# for i in a_tags:
#     print(i['href'])

# 获取职位名称
trs = soup2.find_all('tr')[1:]
for t in trs:
    # print(t)
    # print('*'*50)
    tds = t.find_all('td')[0]
    print(tds.string)

八.select()方法

我们也可以通过css选择器的方式来提取数据。但是需要注意的是这里面我们要掌握的css语法。

CSS 选择器参考手册

python写bs系统 python bs4教程_python写bs系统

https://www.w3school.com.cn/cssref/css_selectors.asp

from bs4 import BeautifulSoup
# select_one()  --> find()
# select() -->  find_all()

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>
"""

soup = BeautifulSoup(html_doc,'lxml')
# select_one等价于find() 只会返回符合条件的第一个结果
# a_tag = soup.select_one('a')
# print(a_tag)
# select()返回所有
# a_tag = soup.select('a')
# print(a_tag)


# 获取class = “sister”的标签
# 选择class="into"的所有元素   --> .into
# 选择class="sister"的所有元素   --> .sister
# tags = soup.select('.sister')
# print(tags)

# 获取id=“link2”的标签
# 选择 id="firstname" 的元素 --》 #firstname
# 选择 id="link2" 的元素 --》 #link2
# tags = soup.select('#link2')
# print(tags)

# # 获取文本内容
# b_tag = soup.select('b')[0]
# # print(b_tag.string)
# print(b_tag.get_text())


html = """
<table class="tablelist" cellpadding="0" cellspacing="0">
    <tbody>
        <tr class="h">
            <td class="l" width="374">职位名称</td>
            <td>职位类别</td>
            <td>人数</td>
            <td>地点</td>
            <td>发布时间</td>
        </tr>
        <tr class="even" id="test">
            <td class="l square"><a target="_blank" href="position_detail.php?id=33824&keywords=python&tid=87&lid=2218">22989-金融云区块链高级研发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-25</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=29938&keywords=python&tid=87&lid=2218">22989-金融云高级后台开发</a></td>
            <td>技术类</td>
            <td>2</td>
            <td>深圳</td>
            <td>2017-11-25</td>
        </tr>
        <tr class="even" id="test">
            <td class="l square"><a target="_blank" href="position_detail.php?id=31236&keywords=python&tid=87&lid=2218">SNG16-腾讯音乐运营开发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>2</td>
            <td>深圳</td>
            <td>2017-11-25</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=31235&keywords=python&tid=87&lid=2218">SNG16-腾讯音乐业务运维工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-25</td>
        </tr>
        <tr class="even">
            <td class="l square"><a target="_blank" href="position_detail.php?id=34531&keywords=python&tid=87&lid=2218">TEG03-高级研发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=34532&keywords=python&tid=87&lid=2218">TEG03-高级图像算法研发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="even">
            <td class="l square"><a target="_blank" href="position_detail.php?id=31648&keywords=python&tid=87&lid=2218">TEG11-高级AI开发工程师(深圳)</a></td>
            <td>技术类</td>
            <td>4</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=32218&keywords=python&tid=87&lid=2218">15851-后台开发工程师</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="even">
            <td class="l square"><a target="_blank" href="position_detail.php?id=32217&keywords=python&tid=87&lid=2218">15851-后台开发工程师</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
        <tr class="odd">
            <td class="l square"><a id="test" class="test" target='_blank' href="position_detail.php?id=34511&keywords=python&tid=87&lid=2218">SNG11-高级业务运维工程师(深圳)</a></td>
            <td>技术类</td>
            <td>1</td>
            <td>深圳</td>
            <td>2017-11-24</td>
        </tr>
    </tbody>
</table>
"""

soup2 = BeautifulSoup(html, 'lxml')
# 1.获取所有tr标签
# trs = soup2.select('tr')
# print(trs)

# 2.获取第三个tr标签
# trs = soup2.select('tr')[2]
# print(trs)

# 3.获取所有class=“even”的标签
# trs = soup2.select('.even')
# trs = soup2.select('tr[class="even"]')
# print(trs)

# 4.获取a标签里面的href属性值
# a_tags = soup2.select('a')
# # print(a_tags)
# for i in a_tags:
#     print(i['href'])


# 5.获取职位名称
trs = soup2.select('tr')[1:]
for i in trs:
    # tds = i.select('td')[0]
    # print(tds.string)
    #使用遍历文档树
    # tds = i.contents
    # print(tds[1].string)
    #将strings强转为列表在取出
    print(list(i.stripped_strings)[0])

九.修改文档树

(1)修改tag的名称和属性;

(2)修改string 属性赋值,就相当于用当前的内容替代了原来的内容;

(3)append()像tag中添加内容,就好像Python的列表的 .append()方法;

(4)decompose()修改删除段落,对于一些没有必要的文章段落我们可以给他删除掉。

from bs4 import BeautifulSoup


'''
修改tag的名称和属性
修改string 属性赋值,就相当于用当前的内容替代了原来的内容
append() 像tag中添加内容,就好像Python的列表的 .append()方法
decompose() 修改删除段落,对于一些没有必要的文章段落我们可以给他删除掉
'''

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>
"""

soup = BeautifulSoup(html_doc,'lxml')
# p_tag = soup.p
# print(p_tag)
# # 修改标签名称
# p_tag.name = 'new_p'
# print(p_tag)
# # 修改属性
# p_tag['class'] = 'newclass'
# print(p_tag)

# 修改文本内容
# p_tag.string = 'new_string'
# p_tag.append('new')  #添加内容
# print(p_tag)

# 删除内容
html = soup.html
print(html)
title = soup.title   #找到待删除的
title.decompose()
print("*"*50)
print(html)