一、 引言

在《第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问》和《第14.11节 Python中使用BeautifulSoup解析http报文:使用查找方法快速定位内容》介绍了通过属性和查找方法定位HTML报文的内容的方法,除了这两种方法还有一种方法就是通过使用CSS选择器的语法找到tag,关于css选择器老猿在此不进行介绍,大家可以自行查找文档了解,老猿推荐W3School 的《CSS 选择器参考手册》。其实不了解也问题不大,本节的内容绝大部分还是很好理解的。

二、 select方法

  1. 语法调用:

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

  2. 语法释义

    1)参数selector为css选择器,关于CSS 选择器,请参考W3School 的《CSS 选择器参考手册》,具体应用方法请见第三部分;

    2)namespace:为一个映射css选择器名字空间到名字空间URIs的字典,老猿对css选择器没有研究过,使用时一般用缺省参数

    3)limit:限制查找到的内容个数,缺省不限制个数;

    4)kwargs:老猿没有查到相关资料,暂时不使用;

    5)返回值为一个列表,里面包含所有满足条件的html元素。

关于select的参数,官网上没有列出,只在举例中使用了第一个参数,老猿是通过help查出来的参数。不过也说明其他参数不重要,我们也就不关注了。

三、 使用select的几种场景及方法

  1. 本部分的html文本及BeatifulSoap对象定义如下:
  1. >>> html='''<html><head><title>老猿Python</title></head>
  2. <body><div>
  3. <h1 id="l1" class='t1' name="line1">老猿Python第1行</h1>
  4. <h2 id="l2" class='t2' name="line2">老猿Python第2行</h2>
  5. <h3 id="l3" class='t3' name="line3">老猿Python第3行</h3>
  6. <div>
  7. <h1 id="l4" class='t1' name="line4">LaoYuanPython第1行</h1>
  8. <h2 id="l5" class='t2' name="line5">LaoYuanPython第2行</h2>
  9. <h3 id="l6" class='t3' name="line6">LaoYuanPython第3行</h3>
  10. </div>
  11. </div></body></html>'''
  12. >>> soup = BeautifulSoup(html, 'lxml')
  13. >>>
  1. 查找某个名称的所有标签

    要查找某个名称的所有标签,直接在BeatifulSoap对象下调用select,语法如下:

    select(“标签名”)

    如:
  1. >>> soup.select('h1')
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>]
  3. >>>

soup.select(‘h1’)效果与soup.find_all(‘h1’)相同。当然调用也可以从某个标签对象发起,这样是查的该标签对象下所有指定名称的标签。如:

  1. >>> soup.div.div.select('h1')
  2. [<h1 class="t1" id="l1" name="line1">LaoYuanPython1行</h1>]
  3. >>>
  1. 查找某个符合要求的所有标签

    这个功能是“查找某个名称的所有标签”的扩展,也可以说“查找某个名称的所有标签”是本功能的一个特例。

语法为:

select(“css选择器”)

其中css选择器可以是如下内容:

1)标签名:等同于功能“查找某个名称的所有标签”

2)css类名:查找css类名为指定类名的所有html元素,语法为:

select(”.类名”)

注意类名前有个小数点

  1. >>> soup.select('.t1')
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>]
  3. >>>

3)属性名:查找存在属性为指定属性名的所有html元素,语法为:

select(”[属性名]”),如:

  1. >>> soup.select('[class]')
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h3 class="t3" id="l3" name="line3">老猿Python3行</h3>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>, <h2 class="t2" id="l2" name="line2">LaoYuanPython2行</h2>, <h3 class="t3" id="l3" name="line3">LaoYuanPython第3行</h3>]
  3. >>> soup.select('[name]')
  4. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h3 class="t3" id="l3" name="line3">老猿Python3行</h3>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>, <h2 class="t2" id="l2" name="line2">LaoYuanPython2行</h2>, <h3 class="t3" id="l3" name="line3">LaoYuanPython第3行</h3>]
  5. >>>

4)属性名+属性值查找:

  1. >>> soup.select("[name='line5']")
  2. [<h2 class="t2" id="l5" name="line5">LaoYuanPython2行</h2>]
  3. >>>

属性名值支持首字符串(使用^符号)匹配、尾字符串匹配(使用$符号)和包含字符串(使用*符号)匹配:

  1. >>> soup.select("[name^='line']") #属性名+属性值开始字符串匹配
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h3 class="t3" id="l3" name="line3">老猿Python3行</h3>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>, <h2 class="t2" id="l5" name="line5">LaoYuanPython2行</h2>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
  3. >>> soup.select("[name$='e5']") #属性名+属性值尾字符串匹配
  4. [<h2 class="t2" id="l5" name="line5">LaoYuanPython2行</h2>]
  5. >>> soup.select("[name*='e5']") #属性名+属性值字符串包含内容匹配
  6. [<h2 class="t2" id="l5" name="line5">LaoYuanPython2行</h2>]
  7. >>>
  8. >>>

5)id名:查找id为指定名字的所有html元素,语法为:

select(”#id名”),如:

  1. >>> soup.select('#l1')
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>]
  3. >>>

6)叠加标签:

上述第2-4种方法,可以在选择器前面叠加一个标签名,就可以实现在上述方法的基础上叠加需要满足标签名的要求的查找条件,如:

  1. >>> soup.select("h1.t1") #标签名+css类名
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
  3. >>> soup.select("h1[name]") #标签名+属性名
  4. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
  5. >>> soup.select("h1[name=line1]") #标签名+属性名+属性值
  6. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>]
  7. >>> soup.select("h1#l4") #标签名+id值
  8. [<h1 class="t1" id="l4" name="line4">LaoYuanPython1行</h1>]

注意以上条件组合时,如果标签和后面叠加内容要求是同一个标签下的内容时,标签和后面内容不能加空格,如果加了空格,就是到标签下的子标签中查找后面叠加内容的元素。如:

  1. >>> soup.select("h1#l4") #查找标签为h1且id为l4的标签
  2. [<h1 class="t1" id="l4" name="line4">LaoYuanPython1行</h1>]
  3. >>> soup.select("h1 #l4") #查找父标签为h1且其下id为l4的子孙标签
  4. []
  5. >>> soup.select("div #l4") #查找父标签为div且其下id为l4的子孙标签
  6. [<h1 class="t1" id="l4" name="line4">LaoYuanPython1行</h1>]
  7. >>>

属性名查找支持模糊查找

  1. >>> soup.select("h3[class$='3']") #标签名+属性名1+属性名+属性值尾字符匹配
  2. [<h3 class="t3" id="l3" name="line3">老猿Python3行</h3>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
  3. >>> soup.select("h1[name^='line']") #标签名+属性名+属性值开始字符串匹配
  4. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
  5. >>>

4. 在某个标签下查找所有子孙节点标签

其中的selector参数填写父标签和子标签名,使用空格分隔,selector参数的实参内容为:“父标签名 子孙标签1 … 子孙标签n”,每个标签鉴间用空格分隔。父标签可以从HTML报文的任意一个标签开始,子孙标签1可以是父标签的直接子标签也可以是更低层次的子孙标签,后面每个子孙标签都是前一个标签的直接子标签或更低层次的子孙标签。如:

  1. >>> soup.div.div.select('h1')
  2. [<h1>LaoYuanPython第一行</h1>]
  3. >>> soup.select('body h2')
  4. [<h2>老猿Python第二行</h2>, <h2>老猿Python第三行</h2>, <h2>LaoYuanPython第二行</h2>, <h2>LaoYuanPython第三行</h2>]
  5. >>> soup.select('body div h2 ')
  6. [<h2>老猿Python第二行</h2>, <h2>老猿Python第三行</h2>, <h2>LaoYuanPython第二行</h2>, <h2>LaoYuanPython第三行</h2>]
  7. >>> soup.select('body div div h2 ')
  8. [<h2>LaoYuanPython第二行</h2>, <h2>LaoYuanPython第三行</h2>]

5. 在某个标签下查找所有直接子标签

其中的selector参数填写父标签和子标签名,使用大于号分隔,selector参数的实参内容为:“父标签名>子孙标签1> …> 子孙标签n”,每个标签鉴间用大于号分隔。父标签可以从HTML报文的任意一个标签开始,子孙标签1必须是父标签的直接子标签,后面每个子孙标签都是前一个标签的直接子标签。如:

  1. >>> soup.select('body>div>h2 ')
  2. [<h2>老猿Python第二行</h2>, <h2>老猿Python第三行</h2>]
  3. >>>

6. 查找解析的某个标签后面的兄弟标签

此功能与《第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问》、《第14.11节 Python中使用BeautifulSoup解析http报文:使用查找方法快速定位内容

》介绍的兄弟标签有所不同。

语法如下:

BeautifulSoup.select(“css选择器1 ~ css选择器2”)

该方法是查找css选择器1确认的首个标签后,到该标签后面内容中的兄弟标签中查找满足css选择器2的兄弟标签。如:

  1. >>> soup.select("[name^='line']")
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h3 class="t3" id="l3" name="line3">老猿Python3行</h3>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>, <h2 class="t2" id="l5" name="line5">LaoYuanPython2行</h2>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
  3. >>> soup.select("[name^='line'] ~ [class='t2']")
  4. [<h2 class="t2" id="l2" name="line2">老猿Python2行</h2>, <h2 class="t2" id="l5" name="line5">LaoYuanPython第2行</h2>]
  5. >>>

7. 一次查找多个标签

要查找的标签间用逗号分隔,如:

  1. >>> soup.select("h3.t3,h1#l4")
  2. [<h3 class="t3" id="l3" name="line3">老猿Python3行</h3>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>, <h3 class="t3" id="l6" name="line6">LaoYuanPython3行</h3>]
  3. >>>

四、 select查找的总结

上面罗列了很多html元素通过css选择器来查找的场景,老猿总结select的使用方法如下:

1、 select可以通过只传递一个”css选择器”参数来调用;

2、 ”css选择器”参数可以支持嵌套多个子选择器组合,每个子选择器的构成方式包括:

1)单个标签;

2)单个属性;

3)单个属性值;

4)单个css类;

5)单个id;

6)以上内容的组合,组合时多个组合项之间不能有空格,如:

  1. >>> soup.select("h1#l1[name$='1'].t1")#标签+id+属性尾字符匹配+CSS类的组合查找
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>]
  3. >>> soup.select("h1#l1[name$='1'] .t1") #css类前有空格,会认为是两个子选择器,且相互之间是祖先节点与孙节点的关系
  4. []
  5. >>>

且这些子选择器每相邻的两个子选择器之间可以支持不同的关系组合,包括:

1)父子关系组合:不同的选择器之间用大于号(>)分隔,后一个选择器查找html元素时只能到前一个选择器定位的标签内的直接子节点内查找。如:

  1. >>> soup.select("body>div>h1[class='t1']")
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>]
  3. >>>

2)子孙关系组合:不同的选择器之间用空格分隔,后一个选择器查找html元素时只能到前一个选择器定位的首个标签的子孙节点内查找。如:

  1. >>> soup.select("body div>h1[class='t1']")
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
  3. >>>

3)兄弟关系组合:不同的选择器之间用波浪线(~)分隔,后一个选择器查找html元素时只能到前一个选择器定位的首个标签的后面的兄弟节点内查找。如:

  1. >>> soup.select("div>h1~#l3") #查找div节点的直接子节点h1的后面的id为l3兄弟节点
  2. [<h3 class="t3" id="l3" name="line3">老猿Python3行</h3>]
  3. >>> soup.select("div h1~[class='t3']") #查找div节点的子孙节点h1后面的class属性值为t3的兄弟节点
  4. [<h3 class="t3" id="l3" name="line3">老猿Python3行</h3>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
  5. >>>

4)并列关系组合:不同的选择器之间用逗号(,)分隔,查找时两个选择器之间是或的关系,即只要满足任意一个选择器的条件都认为符合查找要求。

  1. >>> soup.select("div>h1#l1,div>div>h3.t3")
  2. [<h1 class="t1" id="l1" name="line1">老猿Python1行</h1>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
  3. >>>

五、 select_one

除了使用select找出所有满足条件的html元素外,select还有一个姊妹方法select_one,使用方法与select是一样的,只是返回值不同,select_one返回第一个满足条件的html元素,而不是一个列表。

本节详细介绍了使用BeautifulSoup的select方法解析html报文的各种场景,并在介绍各种场景的基础上老猿将select支持的css选择器模式进行了归类总结,包括单个子选择器的组成方式以及多个子选择器两两之间的关系进行了分类。通过这些知识总结,就算对css选择器不熟悉的人也能熟练掌握BeautifulSoup的select解析方法。

老猿Python,跟老猿学Python!

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


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

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

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

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

    一. 引言 在<第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问>介绍了BeautifulSoup对象的主要属性,通过这些属性可以访 ...

  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.12节 Python中其他文件操作方式

    一. 引言 本章老猿主要介绍了Python 内置io模块的文件操作相关功能,其实除了内置io模块可以进行文件操作外,Python的不同模块还提供了多种文件操作方式,下面简单将这些模块和方法介绍一下. ...

  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. C#设计模式-建造者模式(Builder Pattern)

    引言 在软件测试中,一个项目的自动化测试包括UI自动化.API自动化.压力自动化等,把这些不同类型的自动化测试组装在一起变构成了一个项目的自动化测试.通过执行项目的自动化测试变能执行他的所有类型的自动 ...

  2. Dem地形数据转换为cass支持的dat格式教程

    一.获取dem数据各类精度的dem高程数据下载这里不赘述,可以查阅这篇文章:高程数据下载 这里我们以12.5m精度的dem为例进行转换: 二.将dem数据转换为文本我们这里先将地形数据加载入globa ...

  3. Selective Acknowledgment 选项 浅析 1

     抓包的时候,发现 tcp 三次握手中一般会有几个options  一个是mss 一个是ws  一个sack perm 这次主要是来说一说 sack 这个选项: 1. 只重传超时的数据包,比较实用与后 ...

  4. 最长回文子串的Manacher算法

    对于一个比较长的字符串,O(n^2)的时间复杂度是难以接受的.Can we do better? 先来看看解法2存在的缺陷. 1) 由于回文串长度的奇偶性造成了不同性质的对称轴位置,解法2要对两种情况 ...

  5. python之 《pandas》

    pandas稍微比numpy处理数据起来还是要慢一点,pandas呢是numpy的升级版,可以说各有所长,numpy的优势是用来处理矩阵,而pandas的优势是处理数表. 1. Series 线性数表 ...

  6. 一文解析TCP/UDP

    声明:本文部分内容来自互联网.书籍等渠道,表示感谢: 转载请注明出处:@热风.https://www.cnblogs.com/refeng/p/13996657.html 目录 TCP/UDP详解 1 ...

  7. 如何在所有的mon的损坏情况下将数据恢复如初

    本篇主题 在mon无法启动,或者所有的mon的数据盘都损坏的情况下,如何把所有的数据恢复如初 写本章的缘由 在ceph中国的群里有看到一个技术人员有提到,在一次意外机房掉电后,三台mon的系统盘同时损 ...

  8. kettle连接报错

    如何查看端口号 cmd命令行 输入mysql -u root -p密码进入mysql 输入show global variables like 'port'; 就可以看到端口号3306 测试数据库链接 ...

  9. 创建Spring Cloud聚合项目

    使用maven创建单一项目的时候通常用不到聚合项目,创建spring cloud项目时候,由于下面都是一个一个微服务,每个服务对应一个项目,这就需要用到聚合项目,方便对依赖和项目之间的关系进行管理,使 ...

  10. 灵活运用的@RequestParam和@RequestBody

    最近在编写项目的过程中,老出现前后端传递参数格式不一致.不统一的问题,对于一个已经快工作一年的Java程序员来说,实属不合格,所以我就下来好好研究了一下@RequestParam和@RequestBo ...