爬虫学习:Beautiful Soup的使用

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 一个强大的解析工具——Beautiful Soup,只需简单的几段代码就可以完成网页中某个信息的提取,一起来见识一下它的强大之处叭!

一、前言

这一期Python爬虫学习博客将来学习一个强大的解析工具——Beautiful Soup,有了它我们将告别繁琐的正则表示的书写,我们利用简单的几段代码就可以从HTML文档中提取我们想要的信息了。

这是我的学习专栏:Python爬虫学习

里面有很多我在爬虫学习过程中总结的一些知识点,希望能帮助大家从中学到一点知识,我也会逐渐优化自己的博客质量,得到更多人的认可,谢谢!

好啦,废话不多说,我们一起开始今天的学习之旅叭!

二、我的环境

  • 电脑系统:Windows 11
  • 语言版本:Python 3.10
  • 编译器:PyCharm 2022.2

三、准备工作

1、Beautiful Soup强在哪?

它是一个HTML或者XML的解析库,提供了一些简单的Python函数来进行解析处理,例如处理导航、搜索等,在使用它的时候我们不需要考虑编码问题,它会自动将输入的文档转换为Unicode编码,将输出文档转换为UTF-8编码,灵活正常的使用这个解析工具箱一样的库可以帮我们省去很多繁琐的工作。

2、下载安装

和其他库的安装一样,命令如下:

pipinstallbeautifulsoup4

3、该怎么选解析器?

Beautiful Soup需要使用解析器来完成它的解析任务的,你可以使用官方解析器也可以使用一些第三方解析器,这里我列出几个解析器及它们的优缺点。

解析器 优点 缺点
Python标准库 内置标准库,执行速度适中,文档容错能力强 Python2.7.3或3.2.2前的版本中文容错能力差
LXML HTML 速度快,文档容错能力强 需要安装C语言库
LXML XML 速度快,唯一支持XML的解析器 需要安装C语言库
html5lib 提供最好的容错性,以浏览器的方式解析文档,生成HTML5格式的文档 速度慢,不依赖外部扩展

解析器的使用格式都是一样的:

BeautifulSoup(网页源代码, "解析器")

最常用的解释器就是LXML,推荐使用这个。

四、Beautiful Soup的几种基本使用方法

1、节点选择器

我们可以直接使用节点名称就可以直接选择节点,然后使用string属性就可以获得节点内的文本了。

frombs4importBeautifulSoupimportrequestshtml=requests.get('http://exercise.kingname.info/exercise_bs_1.html').content.decode()
soup=BeautifulSoup(html, 'lxml')
print(soup.title)
print("--------------------")
print(type(soup.title))
print("--------------------")
print(soup.title.string)
print("--------------------")
print(soup.head)

它运行的结果是:

<title>测试</title>--------------------<class'bs4.element.Tag'>--------------------测试--------------------<head><title>测试</title></head>

可以看出后面跟什么节点就会返回该节点的内容,另外type返回title节点的类型是“bs4.element.Tag”,这是Beautiful Soup中一个重要的数据结构,Tag有一些属性,例如string属性,调用它可以直接获得节点的文本信息。

值得注意的一点是当有多个节点时,这种选择方式只会选择第一个匹配到的节点。

2、提取各类信息

  • 获取名称
    使用name属性就可以获取节点的名称,例如:
print(soup.title.name)
  • 它运行的结果是:
title
  • 它返回了title节点的节点名称
  • 获取属性
    使用“节点[]”的形式去获取属性值:
print(soup.li["class"])
  • 它运行的结果是:
['info']
  • 这里要注意的是,如果某个属性的值是唯一的就直接返回属性值单个字符串,如果对于某个属性有多个值,例如class属性有很多值,就会以列表的形式返回,并且只会返回第一个匹配到的值。
  • 获取内容
    获取节点内的文本内容之前我们试过了,直接使用“节点.string”的形式匹配节点内的信息。
  • 嵌套选择
    经过选择器选择出来的结果都是Tag类型,所以我们可以在前一个结果的基础上再次嵌套选择下一个节点,例如:
print(soup.title.string)
print(soup.head.title.string)
  • 它运行的结果是:
测试测试
  • 可以看出两者结果一样。

3、关联选择

  • 选择子节点和子孙节点
    想要获取一个节点的子节点,直接调用contents属性就行。
print(soup.div.contents)
  • 它运行的结果是:
['\n', <ul><liclass="info">我需要的信息1</li><liclass="test">我需要的信息2</li><liclass="iamstrange">我需要的信息3</li></ul>, '\n']
  • 可以看到,返回的结果是列表形式,所以contents属性得到的结果是直接子节点组成的列表。
    我们也可也使用children属性来获得相应的信息:
print(soup.div.children)
fori, childinenumerate(soup.div.children):
print(child)
  • 它运行的结果是:
<list_iteratorobjectat0x0000019657BBBDF0><ul><liclass="info">我需要的信息1</li><liclass="test">我需要的信息2</li><liclass="iamstrange">我需要的信息3</li></ul>
  • 可以看出children返回的结果是生成器类型,需要使用for循环把结果遍历出来。
    获取子孙节点的话,直接使用descendants属性:
print(soup.div.descendants)
fori, childinenumerate(soup.div.descendants):
print(child)
  • 它运行的结果是:
<generatorobjectTag.descendantsat0x00000201C06E3F40><ul><liclass="info">我需要的信息1</li><liclass="test">我需要的信息2</li><liclass="iamstrange">我需要的信息3</li></ul><liclass="info">我需要的信息1</li>我需要的信息1<liclass="test">我需要的信息2</li>我需要的信息2<liclass="iamstrange">我需要的信息3</li>我需要的信息3
  • 返回的结果也是生成器类型,仍然需要使用for循环遍历出结果。
  • 选择父节点和祖先节点
    获取某一节点的父节点,可以直接使用parent属性:
print(soup.li.parent)
  • 它运行的结果是:
<ul><liclass="info">我需要的信息1</li><liclass="test">我需要的信息2</li><liclass="iamstrange">我需要的信息3</li></ul>
  • 如果需要继续获取所有祖先节点,可以直接使用parents属性:
print(type(soup.ul.parents))
print("------------------------------------------")
print(list(enumerate(soup.ul.parents)))
  • 它运行的结果是:
<class'generator'>------------------------------------------[(0, <divclass="useful"><ul><liclass="info">我需要的信息1</li><liclass="test">我需要的信息2</li><liclass="iamstrange">我需要的信息3</li></ul></div>), (1, <body><divclass="useful"><ul><liclass="info">我需要的信息1</li><liclass="test">我需要的信息2</li><liclass="iamstrange">我需要的信息3</li></ul></div><divclass="useless"><ul><liclass="info">垃圾1</li><liclass="info">垃圾2</li></ul></div></body>), (2, <html><head><title>测试</title></head><body><divclass="useful"><ul><liclass="info">我需要的信息1</li><liclass="test">我需要的信息2</li><liclass="iamstrange">我需要的信息3</li></ul></div><divclass="useless"><ul><liclass="info">垃圾1</li><liclass="info">垃圾2</li></ul></div></body></html>), (3, <html><head><title>测试</title></head><body><divclass="useful"><ul><liclass="info">我需要的信息1</li><liclass="test">我需要的信息2</li><liclass="iamstrange">我需要的信息3</li></ul></div><divclass="useless"><ul><liclass="info">垃圾1</li><liclass="info">垃圾2</li></ul></div></body></html>)]
  • 可以看到,返回的结果是生成器类型,如果需要返回各个结果的需要使用for循环遍历。
  • 选择兄弟节点
    获取同级节点的方法如下:
frombs4importBeautifulSouphtml="""<html><body>    <p class="search">        谷歌搜索        <a href="https://www.google.com" class="sister" id="link1">            <span>google</span>        </a>        百度        <a href="https://www.baidu.com" class="sister" id="link2">baidu</a>        火狐        <a href="https://www.firefox.com" class="sister" id="link3">firefox</a>        三个都是常用、好用的浏览器    </p></body></html>"""soup=BeautifulSoup(html, 'lxml')
print("下一个兄弟节点:", soup.a.next_sibling)
print("上一个兄弟节点:", soup.a.previous_sibling)
print("前面所有的兄弟节点:", list(enumerate(soup.a.next_siblings)))
print("后面所有的兄弟节点:", list(enumerate(soup.a.previous_siblings)))
  • 它运行的结果是:
下一个兄弟节点:百度上一个兄弟节点:谷歌搜索前面所有的兄弟节点: [(0, '\n        百度\n        '), (1, <aclass="sister"href="https://www.baidu.com"id="link2">baidu</a>), (2, '\n        火狐\n        '), (3, <aclass="sister"href="https://www.firefox.com"id="link3">firefox</a>), (4, '\n        三个都是常用、好用的浏览器\n    ')]
后面所有的兄弟节点: [(0, '\n        谷歌搜索\n        ')]

4、方法选择器

前面我们总结啦一些基础的基于属性来选择的方法,它们都适用于简单的场景,如果进行比较复杂的选择时,就会比较麻烦,所有我们需要学习一些方法选择器的使用。

  • find()和find_all()的语法格式:
    find_all(name, attrs, recursive, text, **kwargs)
    name:就是HTML的标签名,类似于body、div、ul、li。
    attrs:参数的值是一个字典,字典的Key是属性名,字典的Value是属性值,attrs={'class: ‘useful’}。
    recursive:值为True或者False,当它为False的时候,BS4不会搜索子标签。
    text:可以是一个字符串或者是正则表达式,用于搜索标签里面的文本信息。
    **kwargs:表示Key=Value形式的参数,这种方式也可以用来根据属性和属性值进行搜索。这里的Key是属性,Value是属性值。
  • find()方法
frombs4importBeautifulSouphtml="""<div class="panel">  <div class="panel-heading">    <h4>Hello World</h4>  </div>  <div class="panel-body">    <ul class="list" id="list-1">      <li class="element">Java</li>      <li class="element">Python</li>      <li class="element">C++</li>    </ul>    <ul class="list list-small" id="list-2">      <li class="element">Go</li>      <li class="element">JavaScript</li>    </ul>  </div></div>"""soup=BeautifulSoup(html, 'lxml')
print(soup.find(name='ul'))
print("------------------------------------")
print(type(soup.find(name='ul')))
print("------------------------------------")
print(soup.find(class_='list'))
  • 它运行的结果是:
<ulclass="list"id="list-1"><liclass="element">Java</li><liclass="element">Python</li><liclass="element">C++</li></ul>------------------------------------<class'bs4.element.Tag'>------------------------------------<ulclass="list"id="list-1"><liclass="element">Java</li><liclass="element">Python</li><liclass="element">C++</li></ul>
  • find()方法返回的是第一个匹配的节点元素,类型仍然是Tag类型。
  • find_all()方法
frombs4importBeautifulSouphtml="""<div class="panel">  <div class="panel-heading">    <h4>Hello World</h4>  </div>  <div class="panel-body">    <ul class="list" id="list-1">      <li class="element">Java</li>      <li class="element">Python</li>      <li class="element">C++</li>    </ul>    <ul class="list list-small" id="list-2">      <li class="element">Go</li>      <li class="element">JavaScript</li>    </ul>  </div></div>"""soup=BeautifulSoup(html, 'lxml')
print(soup.find_all(name='ul'))
print("------------------------------------")
print(type(soup.find_all(name='ul')[0]))
  • 它运行的结果是:
[<ulclass="list"id="list-1"><liclass="element">Java</li><liclass="element">Python</li><liclass="element">C++</li></ul>, <ulclass="list list-small"id="list-2"><liclass="element">Go</li><liclass="element">JavaScript</li></ul>]
------------------------------------<class'bs4.element.Tag'
  • find_all()方法返回的是列表类型,并且返回了所有符合条件的元素,类型也是Tag类型。
  • 两者的区别:
    find()与find_all()的不同点如下:
    ① find_all()返回的是Beautiful Soup Tag对象组成的列表,
    如果没有找到任何满足要求的标签,就会返回空列表。
    ② find()返回的是一个Beautiful Soup Tag对象,
    如果有多个符合条件的HTML标签,则返回第1个对象,
    如果找不到就会返回None。

5、CSS选择器

CSS选择器直接使用select方法,然后再传入相应的CSS选择器就行。

frombs4importBeautifulSouphtml="""<div class="panel">  <div class="panel-heading">    <h4>Hello World</h4>  </div>  <div class="panel-body">    <ul class="list" id="list-1">      <li class="element">Java</li>      <li class="element">Python</li>      <li class="element">C++</li>    </ul>    <ul class="list list-small" id="list-2">      <li class="element">Go</li>      <li class="element">JavaScript</li>    </ul>  </div></div>"""soup=BeautifulSoup(html, 'lxml')
print(soup.select('.panel .panel-heading'))
print("----------------------------------------------------------")
print(soup.select('ul li'))
print("----------------------------------------------------------")
print(soup.select('#list-2 .element'))

它运行的结果是:

[<divclass="panel-heading"><h4>HelloWorld</h4></div>]
----------------------------------------------------------[<liclass="element">Java</li>, <liclass="element">Python</li>, <liclass="element">C++</li>, <liclass="element">Go</li>, <liclass="element">JavaScript</li>]
----------------------------------------------------------[<liclass="element">Go</li>, <liclass="element">JavaScript</li>]

熟悉Web开发的人肯定对CSS选择器不陌生,如果不懂得话,这部分可以跳过,不过学习爬虫推荐去学习一下有关前端的一些基础知识,方便我们进行数据的爬取。

五、最后我想说

本期的博客内容大致就是这么多了,如果大家觉得内容不够的话,我后续还可以补充一些,但是别人的东西总归没有自己总结的好理解一些,所以我们都需要去自己去学习上网查阅各种资料或者阅读各种书籍,来不断理解并学习透彻某一知识点。

下一期的爬虫博客,我将来总结有关pyquery的使用,进一步学习有关CSS选择器的使用,弄懂前端的一些知识,提高爬取效率。

本人水平有限,上述文章如有错误之处还请大家为我指出,谢谢!

最后,创作不易,期待得到大家的认可,谢谢大家!

目录
相关文章
|
4月前
|
数据采集 存储 XML
高级网页爬虫开发:Scrapy和BeautifulSoup的深度整合
高级网页爬虫开发:Scrapy和BeautifulSoup的深度整合
|
2月前
|
数据采集 Java
爬虫系统学习
爬虫系统学习
|
2月前
|
数据采集
爬虫之bs4学习
爬虫之bs4学习
|
3月前
|
数据采集 存储 JSON
Python爬虫开发:BeautifulSoup、Scrapy入门
在现代网络开发中,网络爬虫是一个非常重要的工具。它可以自动化地从网页中提取数据,并且可以用于各种用途,如数据收集、信息聚合和内容监控等。在Python中,有多个库可以用于爬虫开发,其中BeautifulSoup和Scrapy是两个非常流行的选择。本篇文章将详细介绍这两个库,并提供一个综合详细的例子,展示如何使用它们来进行网页数据爬取。
|
4月前
|
数据采集 XML 数据挖掘
构建高效Python爬虫:探索BeautifulSoup与Requests库的协同工作
【7月更文挑战第31天】在数据驱动的世界里,掌握网络数据采集技术变得尤为重要。本文将深入探讨如何利用Python语言中的BeautifulSoup和Requests库来构建一个高效的网络爬虫。我们将通过实际案例,展示这两个库如何在爬取网页数据时相互配合,以及如何通过简单的编码实现数据的精准抓取。文章不仅提供代码示例,还讨论了在使用这些工具时应注意的一些常见陷阱和最佳实践。无论你是数据分析师、研究人员还是对爬虫技术感兴趣的程序员,这篇文章都将为你提供一个清晰的指导框架,帮助你快速入门并提高你的爬虫技能。
70 1
|
6月前
|
数据采集 XML 前端开发
Python爬虫:BeautifulSoup
这篇内容介绍了Python中BeautifulSoup库的安装和使用。首先,通过在命令行输入`pip install bs4`进行安装,或使用清华源加速。接着讲解BeautifulSoup的基本概念,它是一个用于数据解析的工具,便于处理HTML和XML文档。与正则表达式不同,BeautifulSoup提供更方便的方式来查找和操作标签及其属性。 文章详细阐述了BeautifulSoup的两个主要方法:`find`和`find_all`。`find`方法用于查找单个指定标签,可结合属性字典进行精确选择;`find_all`则返回所有匹配标签的列表。通过这些方法,可以方便地遍历和提取网页元素。
63 0
|
6月前
|
数据采集 存储 JSON
Python爬虫面试:requests、BeautifulSoup与Scrapy详解
【4月更文挑战第19天】本文聚焦于Python爬虫面试中的核心库——requests、BeautifulSoup和Scrapy。讲解了它们的常见问题、易错点及应对策略。对于requests,强调了异常处理、代理设置和请求重试;BeautifulSoup部分提到选择器使用、动态内容处理和解析效率优化;而Scrapy则关注项目架构、数据存储和分布式爬虫。通过实例代码,帮助读者深化理解并提升面试表现。
189 0
|
6月前
|
数据采集 存储 监控
Python爬虫实战:利用BeautifulSoup解析网页数据
在网络信息爆炸的时代,如何快速高效地获取所需数据成为许多开发者关注的焦点。本文将介绍如何使用Python中的BeautifulSoup库来解析网页数据,帮助你轻松实现数据抓取与处理的技术。
|
6月前
|
数据采集 XML 前端开发
Python爬虫 Beautiful Soup库详解#4
BeautifulSoup基础,节点选择器,方法选择器,css选择器【2月更文挑战第14天】
84 1
|
6月前
|
数据采集 XML 数据处理
Python爬虫实战:利用BeautifulSoup解析网页数据
本文将介绍如何利用Python中的BeautifulSoup库来解析网页数据,帮助读者更好地开发爬虫程序,实现自动化数据采集与处理。