Python爬虫之六:Beautiful Soup 4 库

本文介绍了Python的Beautiful Soup 4库,用于HTML和XML文档解析。内容包括库的安装、与lxml的对比、基本使用、四种常见对象(Tag、NavigableString、BeautifulSoup、Comment)的特性和遍历搜索文档树的方法。Beautiful Soup通过DOM解析方式提供方便的数据提取,但性能上可能不如lxml。示例中展示了如何操作Tag对象,以及使用find、find_all和select方法进行查询。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

一、简介

Beautiful Soup 4 库和 lxml 库一样,是python的一个HTML或XML的解析库,我们可以用它来方便的从网页中提取数据,它拥有强大的API和多样的解析方式。

与 lxml 对比:lxml 只会局部遍历,而Beautiful Soup 是基于 HTML DOM 的,它会载入整个文档,解析DOM树,因此时间和内存开销都会很大,所以性能低于 lxml。

1、安装Beautiful Soup 4 库

1、dos命令窗口输入:pip install bs4
2、pycharm 中搜索安装

中文文档:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/

2、三大解析工具对比

解析工具解析速度使用难度
Beautiful Soup简单
lxml中等中等
正则困难

二、简单使用

from bs4 import BeautifulSoup

html ='''
<html>
  <body>
    <div>
      <ul>
        <li class="item-0"><a href="link1.html">first item</a></li>
        <li class="item-1"><a href="link2.html">second item</a></li>
        <li class="item-inactive"><a href="www.baidu.com"><span class="bold">third item</span></a></li>
        <li class="item-1"><a href="link4.html">fourth item</a></li>
        <li class="item-0"><a href="link5.html">fifth item</a></li>
      </ul>

    </div>
  </body>
</html>
'''

soup = BeautifulSoup(html, 'lxml')
print(soup.prettify())

运行结果:

<html>
 <body>
  <div>
   <ul>
    <li class="item-0">
     <a href="link1.html">
      first item
     </a>
    </li>
    <li class="item-1">
     <a href="link2.html">
      second item
     </a>
    </li>
    <li class="item-inactive">
     <a href="www.baidu.com">
      <span class="bold">
       third item
      </span>
     </a>
    </li>
    <li class="item-1">
     <a href="link4.html">
      fourth item
     </a>
    </li>
    <li class="item-0">
     <a href="link5.html">
      fifth item
     </a>
    </li>
   </ul>
  </div>
 </body>
</html>
解释:

1、soup.prettify():按照 HTML 语言的嵌套格式输出 html 代码。
2、Beautiful Soup 可以调用的解析器的特点:
在这里插入图片描述

三、常见的四种对象

1、Tag

Tag对象与XML或HTML原生文档中的tag相同,Beautiful Soup 中所有的标签都是 Tag 类型,并且 Beautiful Soup 的对象其本质上也是一种 Tag 类型。所以其实一些方法,比如 find、find_all并不是 Beautiful Soup 的,而是 Tag 的。

from bs4 import BeautifulSoup

html ='''
<html>
  <body>
    <div>
      <ul>
        <li class="item-0"><a href="link1.html">first item</a></li>
        <li class="item-1"><a href="link2.html">second item</a></li>
        <li class="item-inactive"><a href="www.baidu.com"><span class="bold">third item</span></a></li>
        <li class="item-1"><a href="link4.html">fourth item</a></li>
        <li class="item-0"><a href="link5.html">fifth item</a></li>
      </ul>
      <b><!--这是一个注释--></b>
    </div>
  </body>
</html>

'''

soup = BeautifulSoup(html, 'lxml')
print(type(soup.li), soup.li)

print(soup.li.name)
print(soup.li.attrs)

print(soup.li['class'])
print(soup.li.get('class'))

soup.li['class'] = 'new attr'
print(soup.li)

运行结果:

<class 'bs4.element.Tag'> <li class="item-0"><a href="link1.html">first item</a></li>
li
{'class': ['item-0']}
['item-0']
['item-0']
<li class="new attr"><a href="link1.html">first item</a></li>
解释:

1、soup.li:获取 html 文本中的第一个 li 标签的内容,它是 <class ‘bs4.element.Tag’> 类型。
2、soup.li.name:获取 li 标签的标签名。
3、soup.li.attrs:获取 html 文本中的第一个 li 标签的属性,返回字典类型。
4、soup.li[‘class’],soup.li.get(‘class’):获取 html 文本中的第一个 li 标签的 class 属性值,返回列表类型。
5、soup.li[‘class’] = ‘new attr’ :把 html 文本中的第一个 li 标签的 class 属性值改为 new attr。

2、NavigableString

如果拿到标签后,还想获取标签中的文本内容,那么可以通过 Tag.string 的方式获取。

...ship...
soup = BeautifulSoup(html, 'lxml')
print(type(soup.li.string), soup.li.string)
#运行结果:
#<class 'bs4.element.NavigableString'> first item

查看 NavigableString 类:
在这里插入图片描述
结论:说明 NavigableString 继承于 python 的 str ,所以 str 的方法和属性它都能使用,如下:

st_li = soup.li.string
res = st_li.split(' ')
print(res) #['first', 'item']

3、BeautifulSoup

BeautifulSoup 对象表示一个文档的全部内容,大部分时候,我们可以把它当做 Tag 对象,它支持遍历文档树和搜索文档树中描述的大部分的方法。

...ship...
print(type(soup)) #<class 'bs4.BeautifulSoup'>

查看 BeautifulSoup 类:
在这里插入图片描述
结论:说明 BeautifulSoup 继承于 Tag 类,所以 Tag 的方法和属性它都能使用。

4、Comment

前三种对象基本已经覆盖了 HTML 和 XML 中的所有内容,但是还有一种特殊的对象无法处理,如 HTML 的注释部分。

...ship...
print(type(soup.b.string), soup.b.string)
# <class 'bs4.element.Comment'> 这是一个注释

查看 Comment 类:
在这里插入图片描述
在这里插入图片描述
结论:说明 Comment 继承于 PreformattedString 类,而 PreformattedString 又继承于 NavigableString 类,所以 NavigableString 的方法和属性它都能使用。

四、遍历及搜索文档树

1、contents 和 children

from bs4 import BeautifulSoup

html ='''
<html><head><title>The Dormouse's story</title></head>
    <body>
<p class="title">The Dormouse's story</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>
<b><!--这是一个注释--></b>
<p class="story">...</p>
'''

soup = BeautifulSoup(html, 'lxml')

head_tag = soup.head
print(type(head_tag.contents), head_tag.contents) #<class 'list'> [<title>The Dormouse's story</title>]
print(type(head_tag.children), head_tag.children) #<class 'list_iterator'> <list_iterator object at 0x0000028934A9CA90>
for ite in head_tag.children:
    print(type(ite), ite) # <class 'bs4.element.Tag'> <title>The Dormouse's story</title>
解释:

1、head_tag.contents:获取 title 标签的内容,返回列表类型。
2、head_tag.children:获取 title 标签的内容,返回迭代器类型。

2、string、strings 和 stripped_strings

...ship...
s1 = soup.p.string
print(type(s1), s1) # <class 'bs4.element.NavigableString'> The Dormouse's story

s2 = soup.strings
print(type(s2), s2) # <class 'generator'> <generator object Tag._all_strings at 0x000001C57E767570>
for string in soup.strings:
    print(string)

s3 = soup.stripped_strings
print(type(s3), s3) # <class 'generator'> <generator object Tag.stripped_strings at 0x0000020C3B687D68>
for string in soup.stripped_strings:
    print(string)
解释:

1、soup.p.string:获取第一个 p 标签下的文本,返回字符串类型,如果这个标签下有多行文本,那么将无法获取。
2、soup.strings:获取整个 HTML 文档中的所有文本,不会去掉空白字符,返回生成器类型。
3、soup.stripped_strings:获取整个 HTML 文档中的所有文本,并且会去掉空白字符,返回生成器类型。

3、find 和 find_all

1、find : 找到第一个满足条件的标签后,返回一个元素。
2、find_all :找到所有满足条件的标签后,返回一个列表。

from bs4 import BeautifulSoup

html ='''
<html>
  <body>
    <div>
      <ul>
        <li class="item-0"><a href="link1.html">first item</a></li>
        <li class="item-1"><a href="link2.html">second item</a></li>
        <li class="item-inactive"><a href="www.baidu.com"><span class="bold">third item</span></a></li>
        <li class="item-1"><a href="link4.html">fourth item</a></li>
        <li class="item-0"><a href="link5.html">fifth item</a></li>
      </ul>
      <b><!--这是一个注释--></b>
    </div>
  </body>
</html>
'''
soup = BeautifulSoup(html, 'lxml')

# 获取所有的li标签
lis = soup.find_all('li')

# 获取第二个li标签
li_02 = soup.find_all('li', limit=2)[1]

# 获取class等于item-1的li标签
lis_item1 = soup.find_all('li', class_='item-1') #方式一
lis_item2 = soup.find_all('li', attrs={'class':'item-1'})  #方式二

# 获取所有a标签的href属性值
list_a = soup.find_all('a')
for a in list_a:
    href = a['href']  #也可以写成 href = a.attrs['href']
    print(href)

# 获取所有的文本到一个列表中
list_ul = soup.find_all('ul')
for ul in list_ul:
    infos = list(ul.stripped_strings)
    print(infos)

4、select 方法(CSS语法)

from bs4 import BeautifulSoup

html ='''
<html><head><title>The Dormouse's story</title></head>
    <body>
<p class="title">The Dormouse's story</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>
<b><!--这是一个注释--></b>
<p class="story">...</p>
'''

soup = BeautifulSoup(html, 'lxml')

# 通过标签名查找
print(soup.select('a'))

# 通过类名查找
res = soup.select('.story')
print(len(res), res)

# 通过 id 查找
print(soup.select('#link1'))

# 组合查找
print(soup.select('head title'))

# 属性查找
print(soup.select('a[href="http://example.com/elsie"]'))

# 获取文本内容
print(soup.select('title')[0].get_text())
解释:select 方法是通过利用 CSS 选择器的语法来完成查找HTML标签的。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值