BeautifulSoup(bs4)

BeautifulSoup是python的一个库,最主要的功能是从网页爬取数据,官方是这样解释的:BeautifulSoup提供一些简单,python式函数来处理导航,搜索,修改分析树等功能,其是一个工具库,通过解析文档为用户提供需要抓取的数据,因为简单,所有不需要多少代码就可以写出一个完整的程序

bs4安装

直接使用pip install命令安装

pip install beautifulsoup4

lxml解析器

lxml是一个高性能的Python库,用于处理XMLHTML文档,与bs4相比之下lxml具有更强大的功能与更高的性能,特别是处理大型文档时尤为明显.lxml可以与bs4结合使用,也可以单独使用

lxml安装

同样使用pip install 安装

pip install lxml

其用于在接下来会结合bs4进行讲解

BeautifulSoup浏览浏览器结构化方法

  • .title:获取title标签

    html_doc="""....
    """"
    # 创建beautifulsoup对象 解析器为lxml
    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.title)
    #output-><title>The Dormouse's story</title>
  • .name获取文件或标签类型名称

    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.title.name)
    print(soup.name)
    #output->title
    #[document]
  • .string/.text:获取标签中的文字内容

    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.title.string)
    print(soup.title.text)
    #output->The Dormouse's story
    #The Dormouse's story
  • .p:获取标签

    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.p)
    #output-><p class="title"><b>The Dormouse's story</b></p>
  • .find_all(name,attrs={}):获取所有标签,参数:标签名,如’a’a标签,’p’p标签等等,attrs={}:属性值筛选器字典如attrs={'class': 'story'}

    # 创建beautifulsoup对象 解析器为lxml
    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.find_all('p'))
    print(soup.find_all('p', attrs={'class': 'title'}))
  • .find(name,attrs={}):获取第一次匹配条件的元素

    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.find(id="link1"))
    #output-><a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>
  • .parent:获取父级标签

    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.title.parent)
    #output-><head><title>The Dormouse's story</title></head>
  • .p['class'] :获取class的值

    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.p["class"])
    #output->['title']
  • .get_text():获取文档中所有文字内容

    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.get_text())
    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.
    ...
  • 从文档中找到所有<a>标签的链接

    a_tags = soup.find_all('a')
    for a_tag in a_tags:
    print(a_tag.get("href"))
    #output->https://example.com/elsie
    #https://example.com/lacie
    #https://example.com/tillie

BeautifulSoup的对象种类

当你使用BeautifulSoup 解析一个HTML或XML文档时,BeautifulSoup会整个文档转换为一个树形结构,其中每个结点(标签,文本,注释)都被表示为一个python对象

BeautifulSoup的树形结构

在HTML文档中,根结点通常是<html>标签,其余的标签和文本内容则是其子结点

若有以下一个HTML文档:

<html>
<head>
<title>The Dormouse's story</title>
</head>
<body>
<h1>The Dormouse's story</h1>
<p>Once upon a time...</p>
</body>
</html>
  • 经过BeautifulSoup的解析后,<html>是根结点,与<html>相邻的<head><body>是其子结点,同理可得<title><head>子结点,<h1><p><body>子结点

对象类型

BeautifulSoup有四种主要类型,Tag,NavigableString,BeautifulSoup,Comment

Tag

Tag对象与HTML或XML原生文档中的标签相同,每个Tag对象都可以包含其他标签,文本内容和属性

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

NavigableString

NavigableString对象表示标签内的文本内容,是一个不可变字符串,可以提供Tag对象的.string获取

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

BeautifulSoup

BeautifulSoup对象表示整个文档的内容.其可以被视为一个特殊的Tag对象,但没有名称与属性.其提供了对整个文档的遍历,搜索和修改的功能

soup = BeautifulSoup(html_doc, 'lxml')
print(type(soup))
#output-> <class 'bs4.BeautifulSoup'>

Comment

Comment对象是一个特殊类型的NavigableString对象,表示HTML和XML中的注释部分

# <b><!--This is a comment--></b>
soup = BeautifulSoup(html_doc, 'lxml')
print(type(soup.b.string))
#output-> <class 'bs4.element.NavigableString'>

BeautifulSoup遍历文档树

BeautifulSoup提供了许多方法来遍历解析后的文档树

导航父节点

  • .parent.parents:.parent可以获取当前节点的上一级父节点,.parents可以遍历获取当前节点的所有父辈节点
soup = BeautifulSoup(html_doc, 'lxml')
title_tag = soup.title
print(title_tag.parent)
#<head><title>The Dormouse's story</title></head>
soup = BeautifulSoup(html_doc, 'lxml')
body_tag = soup.body
for parent in body_tag.parents:
print(parent)
#<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 class="sister" href="https://example.com/elsie" id="link1">Elsie</a>,
#....

导航子结点

  • .contents:可以获取当前结点的所有子结点
soup = BeautifulSoup(html_doc, 'lxml')
head_contents = soup.head.contents
print(head_contents)
#output-> [<title>The Dormouse's story</title>]
  • .children:可以遍历当前结点的所有子结点,返回一个list
soup = BeautifulSoup(html_doc, 'lxml')
body_children = soup.body.children for child in body_children:
print(child)
#output-><p class="title"><b>The Dormouse's story</b></p>
#<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>,
#<a class="sister" href="https://example.com/tillie" id="link3">Tillie</a>;
#and they lived at the bottom of a well.</p>
#.....
  • 字符串没有.children.contents属性

导航所有后代节点

.contents.children属性仅包含tag直接子结点,例如标签只有一个直接子结点<title>

#[<title>The Dormouse's story</title>]

<title>标签也包含一个子结点:字符串”The Dormouse's story”,字符串”The Dormouse's story”是<head>标签的子孙结点

  • .descendants属性可以遍历当前结点的所有后代结点(层遍历)
soup = BeautifulSoup(html_doc, 'lxml')
for descendant in soup.descendants:
print(descendant)

节点内容

  • .string

    • 如果tag只有一个NavigableString类型子节点,那么这个tag可以使用.string得到其子节点.

      soup = BeautifulSoup(html_doc, 'lxml')
      print(soup.head.string)
      #The Dormouse's story
      print(soup.title.string)
      #The Dormouse's story
    • 但若tag中包含了多个子节点,tag就无法确定string方法应该调用哪一个字节的内容,则会输出None

      soup = BeautifulSoup(html_doc, 'lxml')
      print(soup.body.string)
      #None
  • .strings.stripped_strings

    • .strings可以遍历获取标签中的所有文本内容,.stripped_strings可以除去多余的空白字符
    soup = BeautifulSoup(html_doc, 'lxml')
    for string in soup.strings:
    print(string)
    #The Dormouse's story
    ...... #The Dormouse's story
    soup = BeautifulSoup(html_doc, 'lxml')
    for string in soup.stripped_strings:
    print(string)
    #The Dormouse's story
    #The Dormouse's story
    #Once upon a time there were three little sisters; and their names were
    #Elsie
    #,
    ...

BeautifulSoup搜索文档树

BeautifulSoup提供了多种方法来搜索解析后的文档树

find_all(name , attrs , recursive , string , **kwargs)

  • find_all()方法搜索当前tag的所有tag子节点
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all("title")) # 查找所有的title标签
print(soup.find_all("p", "title")) # 查找p标签中class为title的标签 print(soup.find_all("a")) # 查找所有的a标签 print(soup.find_all(id="link2")) # 查找id为link2的标签
#[<title>The Dormouse's story</title>]
#[<p class="title"><b>The Dormouse's story</b></p>]
#[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="https://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="https://example.com/tillie" id="link3">Tillie</a>]
#[<a class="sister" href="https://example.com/lacie" id="link2">Lacie</a>]

接下来我们来详细解析一下每个参数的含义

name参数

name参数可以查找所有名字为name的tag,字符串对象名字会自动被忽略

  • eg

    soup.find_all("title")
    # [<title>The Dormouse's story</title>]
  • name参数可以为任意类型的过滤器,如字符串,正则表达式,列表,方法等等

  • 传字符串

    传入字符串是最简单的过滤器,在搜索方法中传入一个字符串参数,BeautifulSoup会查找与字符串匹配的内容

    • 下面的例子用于查找文档中所有的<b>标签
    soup.find_all('b')
    # [<b>The Dormouse's story</b>]
  • 传入正则表达式

    若传入正则表达式作为参数,BeautifulSoup会通过正则表达式match()来匹配内容

    • 查找b开头的标签,这表示<body>和<b>标签都应该被找到
    soup = BeautifulSoup(html_doc, 'lxml')
    for tag in soup.find_all(re.compile("^b")):
    print(tag.name)
    # body
    # b
  • 传入列表

    如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回

    • 找到文档中所有<a>标签和<b>标签
    soup = BeautifulSoup(html_doc, 'lxml')
    for tag in soup.find_all(['a', 'b']):
    print(tag.name)
    #b
    #a
    #a
    #a
    #b

**kwargs参数

在BeautifulSoup中,**kwargs(即关键字参数)可用于通过标签的属性来查找特定的标签.这些关键字参数可以直接传递给find,find_all方法,使得搜索更加强大.标签的属性名作为关键字参数,值可以是字符串、正则表达式或列表

使用字典

  • 可以使用key=’word’传入参数
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all(id='link1'))
#[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>]

使用正则表达式

  • 使用Pythonre模块中的正则表达式来匹配属性值,使搜索更灵活
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all('a', href=re.compile("elsie"))) # 查找href属性中包含elsie的a标签
print(soup.find_all(string=re.compile("^The"))) # 查找文本中The开头的标签
#[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>]
#["The Dormouse's story", "The Dormouse's story"]

使用列表

  • 可以传递一个列表作为关键字参数的值.BeautifulSoup会匹配列表中的任意一个值
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find('a', id=['link1', 'link2'])) # 查找id为link1或者link2的a标签
print(soup.find_all(class_=['sister', 'story'])) # 查找class为sister或者story的标签
#<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>
#[<p class="story">Once upon a time there were three little sisters; and their names were
#...

特殊属性名称

HTML的属性名称与Python的保留字冲突,为了防止冲突,BeautifulSoup提供了一些特殊的替代名称

  • class_:用于匹配class属性
  • data-*:用于匹配自定义的data-*属性
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all('p', class_="title")) # 查找所有class为title的p标签
print(soup.find_all('p', attrs={'data-p', 'story'})) # 查找所有class为story的p标签
#[<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 class="sister" href="https://example.com/elsie" id="link1">Elsie</a>,
#<a class="sister" href="https://example.com/lacie" id="link2">Lacie</a> and

text/string参数

text/string参数允许操作者根据标签的文本内容进行搜索,与name参数类似,text参数也支持多种类型的值,包括正则表达式,字符串列表和True,早期bs4支持text,近期bs4text都改为string

使用字符串匹配

你可以直接传递一个字符串作为 string参数的值,BeautifulSoup 会查找所有包含该字符串的标签

soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all(string='Elsie'))
#['Elsie']

使用正则表达式匹配

soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all(string=re.compile('sister'), limit=2)) # 查找前两个包含sister的字符串
print(soup.find_all(string=re.compile('Dormouse'))) # 查找包含Dormouse的字符串
#['Once upon a time there were three little sisters; and their names were\n']
#["The Dormouse's story", "The Dormouse's story"]

使用列表匹配

soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all(string=['Elsie', 'Lacie', 'Tillie']))
#['Elsie', 'Lacie', 'Tillie']

limit参数

BeautifulSoup中的limit参数用于限制find_all方法结果的返回数量,当只需要查询前几个标签时,使用limit参数可以提高搜索搜索效率,效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果

soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all('a', limit=2)) # 查找所有a标签,限制输出2个
#[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="https://example.com/lacie" id="link2">Lacie</a>]

find_parents() 和 find_parent()

BeautifulSoup 提供了 find_parents()find_parent() 方法,用于在解析后的文档树中向上查找父标签.两个方法的主要区别在于返回的结果数量

  • find_parent(name=None, attrs={}, **kwargs):只返回最接近的父标签(即第一个匹配的父标签)
  • find_parents(name=None, attrs={}, limit=None, **kwargs):返回所有符合条件的祖先标签,按从近到远的顺序排列
soup = BeautifulSoup(html_doc, 'lxml')
a_string = soup.find(string='Lacie')
print(a_string.find_parent()) # 查找父节点
print('-----------------')
print(a_string.find_parents()) # 查找所有父节点
#<a class="sister" href="https://example.com/lacie" id="link2">Lacie</a>
#-----------------
#[<a class="sister" href="https://example.com/lacie" id="link2">Lacie</a>, <p class="story">Once upon a time there were three little sisters; and their names were
#<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>,
#<a class="sister" href="https://example.com/lacie" id="link2">Lacie</a> and
#and they lived at the bottom of a well.</p>, <body>....]

BeautifulSoup的CSS选择器

我们在写CSS时,标签名不加任何修饰,类名前加点,id名前加#,BeautifulSoup中也可以使用类似的方法来筛选元素,

select(selector, namespaces=None, limit=None, **kwargs)

BeautifulSoup中的select()方法允许使用CSS选择器来查找HTML文档元素,其返回一个包含所有匹配元素的列表类似与find_all()方法

  • selector:一个字符串,表示将要选择的CSS选择器,可以是简单标签选择器,类选择器,id选择器

通过标签名查找

soup = BeautifulSoup(html_doc, 'lxml')
print(soup.select('b'))
#[<b>The Dormouse's story</b>, <b><!--This is a comment--></b>]

通过类名查找

soup = BeautifulSoup(html_doc, 'lxml')
print(soup.select('.title'))
#[<p class="title"><b>The Dormouse's story</b></p>]

id名查找

soup = BeautifulSoup(html_doc, 'lxml')
print(soup.select('#link1'))
#[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>]

组合查找

  • 组合查找即与写class时一致,标签名与类名id名进行组合的原理一样

eg:查找p标签中id为link1的内容

soup = BeautifulSoup(html_doc, 'lxml')
print(soup.select('p #link1'))
#[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>]
  • 查找类选择器时也可以使用id选择器的标签
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.select('.story#text'))
  • 查找有多个class选择器和一个id选择器的标签
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.select(".story .sister#link1"))
#[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>]

属性查找

选择具有特定属性或属性值的标签

  • 简单属性选择器

    • 选择具有特定属性的标签
    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.select("a[href='https://example.com/elsie']")) # 选择a标签中href属性为https://example.com/elsie的标签
    #[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>]
  • 属性值选择器

    选择具有特定属性值的标签

    • 精确匹配:[attribute="value"]
    • 部分匹配
      • 包含特定值:[attribute~="value"] 选择属性值包含特定单词的标签。
      • 以特定值开头:[attribute^="value"] 选择属性值以特定字符串开头的标签
      • 以特定值结尾:[attribute$="value"] 选择属性值以特定字符串结尾的标签。
      • 包含特定子字符串:[attribute*="value"] 选择属性值包含特定子字符串的标签
    soup = BeautifulSoup(html_doc, 'lxml')
    print(soup.select('a[href^="https://example.com"]')) # 选择href以https://example.com开头的a标签
    #[<a class="sister" href="https://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="https://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="https://example.com/tillie" id="link3">Tillie</a>]

BeautifulSoup(bs4)细致讲解的更多相关文章

  1. 微信小程序入门与实战 从0到1进行细致讲解 涵盖小程序开发核心技能下载

    第1章 什么是微信小程序? 第2章 小程序环境搭建与开发工具介绍 第3章 从一个简单的“欢迎“页面开始小程序之旅 第4章 第二个页面:新闻阅读列表 第5章 小程序的模板化与模块化 第6章 构建新闻详情 ...

  2. from bs4 import BeautifulSoup 报错

    一: BeautifulSoup的安装: 下载地址:https://www.crummy.com/software/BeautifulSoup/bs4/download/4.6/ 下载后,解压缩,然后 ...

  3. python库:bs4,BeautifulSoup库、Requests库

    Beautiful Soup https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/ Beautiful Soup 4.2.0 文档 htt ...

  4. python bs4 BeautifulSoup

    Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.bs4 模块的 BeautifulSoup 配合requests库可以写简单的爬虫. 安装 命令:pip in ...

  5. from bs4 import BeautifulSoup 引入需要安装的文件和步骤

    调用beautifulsoup库时,运行后提示错误: ImportError: No module named bs4 , 意思就是没有找到bs4模块,所以解决方法就是将bs4安装上,具体步骤如下: ...

  6. python爬虫知识点总结(六)BeautifulSoup库详解

    官方学习文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/ 一.什么时BeautifulSoup? 答:灵活又方便的网页解析库,处 ...

  7. Python爬虫小白入门(三)BeautifulSoup库

    # 一.前言 *** 上一篇演示了如何使用requests模块向网站发送http请求,获取到网页的HTML数据.这篇来演示如何使用BeautifulSoup模块来从HTML文本中提取我们想要的数据. ...

  8. BeautifulSoup研究一

    BeautifulSoup的文档见 https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/ 其中.contents 会将换行也记录为一个子节 ...

  9. bs4 python解析html

    使用文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/ python的编码问题比较恶心. decode解码encode编码 在文件 ...

  10. urllib+BeautifulSoup无登录模式爬取豆瓣电影Top250

    对于简单的爬虫任务,尤其对于初学者,urllib+BeautifulSoup足以满足大部分的任务. 1.urllib是Python3自带的库,不需要安装,但是BeautifulSoup却是需要安装的. ...

随机推荐

  1. webpack笔记-生产环境与开发环境常用plugin介绍(五)

    mode 和 plugin 前边我们介绍 mode 时提过,mode 不同值会影响 webpack 构建配置,其中有一个就是会启用 DefinePlugin 来设置process.env.NODE_E ...

  2. 人脸伪造图像检测:Deepfake魔高一尺,TextIn道高一丈

      只因开了一个视频会议,直接被骗1.8个亿 今年2月,一家跨国公司的香港分公司财务人员被一场精心策划的Deepfake视频会议诈骗,导致公司损失2亿港币(约1.8亿人民币). 事件起因是财务人员收到 ...

  3. c# 常用反射和表达式树整理

    更新: 2021-06-19 反射 local function https://stackoverflow.com/questions/43348128/reflection-how-do-i-fi ...

  4. [TK] 颜色

    谴责这道题发明在线莫队的人,简直就是异端,还好我给在线莫队卡了,支持正义制裁 题意简述 给定序列,设 \(f(l,r,x)\) 表示 \(x\) 在 \([l,r]\) 内的出现次数,对给定 \(l, ...

  5. ShardingSphere系列(一)——ShardingSphere-JDBC初体验

    Apache ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈,它由 JDBC.Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品 ...

  6. vue前端开发仿钉图系列(6)左侧记事本的开发详解

    在页面开发中,深深的被element组件所吸引,里面很多小组件都可以直接使用.像是记事本提示.记事本列表时间线.右侧编辑页面的form表单,编辑和查看状态的切换等等,比之前iOS原生开发所有的东西都要 ...

  7. iOS关于搜索不规则瀑布流布局的实现小结

    最近在项目开发中遇到了不规则搜索布局的问题.之前常用的解决方案是用一个tableview用一个循环动态的加载,唯一的缺点是需要动态的移除,其实也已经足够.https://download.csdn.n ...

  8. 018 人生中第一次用 Python 写的一个小程序_猜年龄(再次强调,重视基础)

    博客配套视频链接: https://space.bilibili.com/383551518?spm_id_from=333.1007.0.0 b 站直接看 配套 github 链接:https:// ...

  9. udev简介与使用

    部分参考自: https://www.cnblogs.com/fah936861121/p/6496608.html 什么是udev udev是Linux(linux2.6内核之后)默认的设备管理工具 ...

  10. NetCore项目发布对前端项目进行打包合并发布

    在某个小项目中, api使用asp.net core 3.x 编写, UI页面则使用Vuejs. 正常情况下, 项目右键的发布只会发布api项目,而不会管Vuejs的项目. 所以通过简单的改造,在发布 ...