一、 引言

在《第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问》介绍了BeautifulSoup对象的主要属性,通过这些属性可以访问标签、内容,但这种方法要么就只能访问符合条件的第一个对象,要么需要遍历访问对象,某些情况下不能通过指定特征快速定位标签和内容。本节将介绍使用BeautifulSoup提供的相关方法快速定位标签和内容的方法。本节继续复用《第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问》中的HTML文件和对象定义代码。

本节案例中介绍处理的c:\temp\s1.html文件内容如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<style type="text/css"> .textline{color:blue;}</style>
<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>
<title>BeautifulSoups使用方法 - 老猿Python - CSDN博客 </title></head>
<body>
<h1>老猿Python</h1>
<div><p class="textline" name="line1"> 老猿Python首行</p></div>
<div>
<h2>老猿Python第二行<a href="https://blog.csdn.net/LaoYuanPython" /> </h2>
<h3><b>老猿Python第三行</b><a href="https://blog.csdn.net/LaoYuanPython" /> </h3>
</div>
</body></html>

创建soup对象的代码如下:

>>> from bs4 import BeautifulSoup
>>> def getsoup():
fp = open(r'c:\temp\s1.html',encoding='utf-8')
soup = BeautifulSoup(fp, 'lxml')
fp.close()
print(soup)
return soup >>> soup=getsoup()

二、 方法find_all

find_all() 方法搜索当前标签的所有子节点,并判断是否符合过滤器的条件,非标签标记的字符串对象会被自动忽略掉。

1、 调用语法:find_all( name , attrs , recursive , string ,limit, **kwargs )

2、 name 参数:匹配过滤器,用于查找所有名字满足name过滤器 的标签。 过滤器有几种类型:

1)字符串:传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的标签名,注意是完整匹配,不是模糊匹配;

>>> soup.find_all('link')
[<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>]
>>>

2)正则表达式:传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配标签名。注意在这个地方传入必须是re.compile的匹配模式,如果是匹配字符串Python会认为是字符串匹配。

>>> soup.find_all(re.compile('h[1-2]'))
[<h1>老猿Python</h1>, <h2>老猿Python第二行<a href="https://blog.csdn.net/LaoYuanPython"></a> </h2>]

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

>>> soup.find_all(['h1','h2'])
[<h1>老猿Python</h1>, <h2>老猿Python第二行<a href="https://blog.csdn.net/LaoYuanPython"></a> </h2>]
>>>

4)True:True 可以匹配任何标签,将查找所有的标签;

5)方法:传一个方法,该方法只有一个标签参数,通过这个方法对标签进行一些校验,满足条件返回 True 表示当前元素匹配并且被找到,如果不是则返回 False。如:

>>> def findline(tag):

    if tag==None: return False
content=tag.attrs.get('name')
if content==None:return False
return re.match('line',content)!=None >>> soup.find_all(findline)
[<p class="textline" name="line1"> 老猿Python首行</p>]
>>>

Beautiful Soup官网文档地址:https://beautifulsoup.readthedocs.io/zh_CN/latest/给了个例子:

def has_class_but_no_id(tag):
return tag.has_attr('class') and not tag.has_attr('id')

将这个方法作为参数传入 find_all() 方法,将得到所有有class属性但无id属性的标签。

3、 kwargs参数

如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字标签的属性来搜索。如包含一个名字为 id 的参数,Beautiful Soup会搜索每个标签的”id”属性。

搜索方法语法如下:

属性id=匹配过滤器

其中属性id要求是个合法的Python标识符,否则需要使用attrs参数才能进行匹配。匹配过滤器与name参数类似,稍有差别,主要是不支持列表方式传参,同时其匹配的内容是属性id对应的值,而不是标签或属性id,匹配是去查看对应属性的值是否满足条件。

1)根据属性值的字符串来匹配,注意是必须完全相同,如:

>>> soup.find_all(rel='canonical')
[<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>]

2)根据属性值的正则表达式使用match来匹配,如:

>>> soup.find_all(href=re.compile('.*'))
[<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>, <a href="https://blog.csdn.net/LaoYuanPython"></a>, <a href="https://blog.csdn.net/LaoYuanPython"></a>]
>>>

3)属性ID=True来匹配所有有该属性的标签,如:

>>> soup.find_all(rel=True)
[<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>]
>>> soup.find_all(href=True)
[<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>, <a href="https://blog.csdn.net/LaoYuanPython"></a>, <a href="https://blog.csdn.net/LaoYuanPython"></a>]
>>>

4)方法:传一个方法,该方法只有一个参数,这个参数在调用时传递的实参时对应属性ID的属性值,通过这个方法对属性值进行一些校验,满足条件返回 True 表示当前元素匹配并且被找到,如果不是则返回 False

>>> def gethrefinludeaticle(value):
if value==None:return False
return re.findall('article',value) >>> soup.find_all(href=gethrefinludeaticle)
[<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>]
>>>

注意:经老猿验证测试,发现在校验函数调用前,系统并没有先进行属性id的匹配成功再调用校验函数,而是所有标签属性匹配失败也会进入校验函数再校验,此时因为匹配失败value为None,因此对校验函数的参数进行None的判断非常重要。如果我们将value的情况输出,可以清楚看到函数的调用情况。如:

>>> def gethrefinludeaticle(value):
if value==None:
print("None")
return False
else:print(value)
return re.findall('article',value) >>> soup.find_all(href=gethrefinludeaticle)
None
None
None
https://blog.csdn.net/LaoYuanPython/article/details/95360624
None
None
None
None
None
None
None
https://blog.csdn.net/LaoYuanPython
None
None
https://blog.csdn.net/LaoYuanPython
None
None
[<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>]
>>>

5)属性id为Python关键字class的匹配

按照CSS类名搜索tag的功能非常实用,但标识CSS类名的关键字 class 在Python中是保留字,使用 class 做参数会导致语法错误。

可以通过给class加下划线变成 class_进行搜索,如:

>>> soup.find_all(class='textline')
SyntaxError: invalid syntax
>>> soup.find_all(class_='textline')
[<p class="textline" name="line1"> 老猿Python首行</p>]

由于tag的 class 属性是 多值属性 .按照CSS类名搜索tag时,可以分别搜索tag中的每个CSS类名,如:

css_soup = BeautifulSoup('<p class="body strikeout"></p>')
css_soup.find_all("p", class_="strikeout")
# [<p class="body strikeout"></p>] css_soup.find_all("p", class_="body")
# [<p class="body strikeout"></p>]
搜索 class 属性时也可以通过CSS值完全匹配: css_soup.find_all("p", class_="body strikeout")
# [<p class="body strikeout"></p>]

4、 attrs参数

根据属性id和属性值的字典来匹配,可以使用“attrs=字典”,字典的元素的键是带引号的标签属性id,在属性id不是一个合法的Python标识符情况下,可以使用这种方法来匹配。根据老猿的测试验证,注意:class不能再加下划线,字典的值可以是上面所有的匹配方法,多个字典元素是与的关系,即要找到的标签必须具有字典中所有元素对应的内容。这可是网上的资料及beatifulsoap官网都没介绍。如:

>>> def gethrefinludeaticle(value):
if value==None: return False
return re.findall('article',value) >>> soup.find_all(attrs={'href':gethrefinludeaticle,'rel':'canonical'})
[<link href="https://blog.csdn.net/LaoYuanPython/article/details/95360624" rel="canonical"/>]
>>> soup.find_all(attrs={'class':re.compile('.*')}) [<p class="textline" name="line1"> 老猿Python首行</p>]
>>> soup.find_all(attrs={'class_':re.compile('.*')}) #class不能加下划线 []
>>>

5、 recursive参数

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

6、 string参数

通过 string 参数可以搜搜文档中的字符串内容。与 name 参数的可选值一样, string 参数接受 字符串 , 正则表达式 , 列表, True 。

新版本该参数名为string,老版本中为text,根据老猿的验证这两个参数使用效果是一样的,不过建议使用string。 如:

>>> soup.find_all(text=re.compile('.*'))

['html', '\n', '\n', '\t.textline{color:blue;}', '\n', '\n', 'BeautifulSoups使用方法 - 老猿Python - CSDN博客 ', '\n', '\n', '老猿Python', '\n', ' 老猿Python首行', '\n', '\n', '老猿Python第二行', ' ', '\n', '老猿Python第三行', ' ', '\n', '\n', '\nkeyword 参数\n如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.\t']

>>> soup.find_all(string=re.compile('.*'))

['html', '\n', '\n', '\t.textline{color:blue;}', '\n', '\n', 'BeautifulSoups使用方法 - 老猿Python - CSDN博客 ', '\n', '\n', '老猿Python', '\n', ' 老猿Python首行', '\n', '\n', '老猿Python第二行', ' ', '\n', '老猿Python第三行', ' ', '\n', '\n', '\nkeyword 参数\n如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.\t']

7、 limit 参数

该参数在官网的方法定义中没有,但后面参数介绍中有,经过验证是可以使用的,因此老猿将其补充到参数中去了。使用 limit 参数限制返回结果的数量,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果。

8、 返回值

find_all的返回值是一个符合条件的html元素列表,每个元素就是一个符合条件的html元素。find_all()只搜索当前节点的所有子节点,孙子节点等。

三、 find_all方法的简写使用

find_all() 是Beautiful Soup中最常用的搜索方法,所以Beautiful Soup定义了它的缩写方法。具体缩写方式为:

将“BeautifulSoup对象.find_all(参数)” 缩写为“BeautifulSoup对象(参数)”

如代码:soup.find_all(“a”)与soup(“a”)是等价的,soup.title.find_all(string=True)与soup.title(string=True)等价。

四、 find

find() 搜索当前节点的所有子节点,孙子节点等是否有满足条件的元素,有则返回第一个符合条件的内容。

1. 调用语法:

find( name , attrs , recursive , string , **kwargs );

2. 语法释义:

find的几个参数与find_all中同名参数是一样的,参数含义也是一样,只是比find_all少了一个limit参数。而返回值是直接返回第一个满足条件的html元素。find_all() 方法没有找到目标是返回空列表,find() 方法找不到目标时返回 None 。某种程度上讲,find类似于find_all中参数limit=1的调用。

3.通过“对象.标签名”访问是“对象.find(”标签名”)”的简写,如:soup.head.title是soup.find(“head”).find(“title”)的简写。

五、 find_parents() 和 find_parent()

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

  1. 调用语法:

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

    find_parent( name , attrs , recursive , string , **kwargs )
  2. 语法释义

    find_parents() 和 find_parent()几个参数与find_all中同名参数是一样的,参数含义也是一样,只是比find_all少了一个limit参数。

    find_parents搜索父辈节点的方法实际上就是对 parents 属性的迭代搜索,返回值是一个列表。find_parent就是返回第一个符合条件的父节点的html元素,与parent属性含义是一样,只是parent只能通过“对象.parent”方式访问,而find_parent可以去父节点中查找满足条件的父节点。

六、 find_next_siblings() 和 find_next_sibling()

这2个方法通过 next_siblings 属性查找当前标签的所有后面解析的兄弟标签节点。

  1. 调用语法:

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

    find_next_sibling( name , attrs , recursive , string , **kwargs )
  2. 语法释义

    相关参数的含义与find_all的同名参数含义一致,find_next_siblings() 方法返回所有符合条件的后面的兄弟节点,find_next_sibling() 只返回符合条件的后面的第一个tag节点。

七、 find_previous_siblings() 和 find_previous_sibling()

这两个方法通过 previous_siblings 属性对当前tag的前面解析的兄弟tag节点进行迭代查找满足条件的节点。

  1. 调用语法:

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

    find_previous_sibling( name , attrs , recursive , string , **kwargs )
  2. 语法释义

    这2个方法的参数与find_all中同名参数用途是一样的。find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点的列表,find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点。

八、 find_all_next() 和 find_next()

这2个方法通过 next_elements 属性对当前标签之后的标签和字符串进行迭代查找满足要求的数据。

  1. 调用语法:

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

    find_next ( name , attrs , recursive , string , **kwargs )
  2. 语法释义:

    这2个方法的参数与find_all中同名参数用途是一样的。find_all_next() 方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点。

九、 find_all_previous() 和 find_previous()

这2个方法通过 previous_elements 属性对当前节点前面的tag和字符串进行迭代查找符合条件的节点。

  1. 调用语法:

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

    find_previous( name , attrs , recursive , string , **kwargs )
  2. 语法释义:

    这2个方法的参数与find_all中同名参数用途是一样的。find_all_previous () 方法返回所有符合条件的节点, find_previous 方法返回第一个符合条件的节点。

本节介绍了BeautifulSoup查找类的主要方法,通过这些方法可以找到符合条件的html元素。本节文档老猿在BeautifulSoup官网的基础之上验证测试之后整理而成,文档结构大部分内容与官网内容,但有老猿验证之后的一些比较独特的内容。

老猿Python,跟老猿学Python!

博客地址:https://blog.csdn.net/LaoYuanPython


老猿Python博客文章目录:https://blog.csdn.net/LaoYuanPython/article/details/98245036

请大家多多支持,点赞、评论和加关注!谢谢!

第14.11节 Python中使用BeautifulSoup解析http报文:使用查找方法快速定位内容的更多相关文章

  1. 第14.12节 Python中使用BeautifulSoup解析http报文:使用select方法快速定位内容

    一. 引言 在<第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问>和<第14.11节 Python中使用BeautifulSo ...

  2. 第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问

    一. 引言 在<第14.8节 Python中使用BeautifulSoup加载HTML报文>中介绍使用BeautifulSoup的安装.导入和创建对象的过程,本节介绍导入后利用Beauti ...

  3. 第14.8节 Python中使用BeautifulSoup加载HTML报文

    一. 引言 BeautifulSoup是一个三方模块bs4中提供的进行HTML解析的类,可以认为是一个HTML解析工具箱,对HTML报文中的标签具有比较好的容错识别功能.阅读本节需要了解html相关的 ...

  4. 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解

    第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一.    引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...

  5. 第8.23节 Python中使用sort/sorted排序与“富比较”方法的关系分析

    一. 引言 <第8.21节 Python中__lt__.gt__等 "富比较"("rich comparison")方法用途探究>和<第8.2 ...

  6. 第14.9节 Python中使用urllib.request+BeautifulSoup获取url访问的基本信息

    利用urllib.request读取url文档的内容并使用BeautifulSoup解析后,可以通过一些基本的BeautifulSoup对象输出html文档的基本信息.以博文<第14.6节 使用 ...

  7. 第9.11节 Python中IO模块文件打开读写操作实例

    为了对前面学习的内容进行一个系统化的应用,老猿写了一个程序来进行文件相关操作功能的测试. 一. 测试程序说明 该程序允许测试人员选择一个文件,自己输入文件打开模式.写入文件的位置以及写入内容,程序按照 ...

  8. 第9.10节 Python中IO模块其他文件操作属性和方法简介

    本文中所有案例中的fp都是使用open函数打开文件返回的一个文件对象,为了节省篇幅,大部分没有提供文件打开的代码. 一. 文件是否关闭的属性 属性名:closed 功用:判断文件是否关闭 示例: &g ...

  9. 第8.27节 Python中__getattribute__与property的fget、@property装饰器getter关系深入解析

    一. 引言 在<第7.23节 Python使用property函数定义属性简化属性访问的代码实现>和<第7.26节 Python中的@property装饰器定义属性访问方法gette ...

随机推荐

  1. slam-g2o安装失败的解决问题

    1.安装依赖项libqglviewer-dev出问题 原因: ubuntu16.04或者14.04不能直接sudo apt-get install libqglviewer-dev. 使用三个包来安装 ...

  2. Python基础学习之常用模块

    1. 模块 告诉解释器到哪里查找模块的位置:比如sys.path.append('C:/python') 导入模块时:其所在目录中除源代码文件外,还新建了一个名为__pycache__ 的子目录,这个 ...

  3. 都知道的copy_from_user

    Q:一直知道内核和用户态的数据交互前都需要 校验地址的合法性,一般都用copy_from/to_user完成数据拷贝,那么为什么要这样呢?? A:看了一些blog以及Stack Overflow 主要 ...

  4. PEP8编程规范

    1.PEP8编程规范 [少加空格多写注释,严格对齐] 1.缩进 缩进table = 4个空格:设置好后使用编辑器的自然table 2.if条件书写规范 if的条件多的时候用左边括号对齐:if条件完毕后 ...

  5. React native路由跳转navigate、push、replace的区别

    由于没有系统的去学习RN,对路由跳转了解不多,只是跟着项目在做,抽点时间简单学习一下RN路由跳转方法区别,总结如下: 如上图,外部是一个栈容器,此时A页面在最底部,navigate到B页面,为什么此时 ...

  6. C#设计模式——代理模式(Proxy Pattern)

    引言 在我们的生活中,经常会遇到需要什么东西,但是自己又不是很方便或者对方不是很方便,则就需要中间的一个代理人去解决.例如代购.在软件开发中,也会遇到这样的问题.有些对象有时候会由于网络或其他的障碍, ...

  7. php 判断网站是http还是https

    //判断是http还是https $http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (i ...

  8. webug第十二关:我系统密码忘记了!

    第十二关:我系统密码忘记了! 文件上传 直接上传php一句话, 菜刀链接

  9. C#实现SM2国密加密

    本文主要讲解"国密加密算法"SM系列的C#实现方法,不涉及具体的算法剖析,在网络上找到的java实现方法比较少,切在跨语言加密解密上会存在一些问题,所以整理此文志之.JAVA实现参 ...

  10. DocView 现在支持自定义 Markdown 模版了!

    前言 有小伙伴反馈说希望可以自定义 Markdown 模版,这样就可以导出自己想要的样式了!这个功能可以有,毕竟大家不可能都生成一模一样的文档.现在来一起看看如何实现自定义模版吧! 设置模版 Sett ...