第14.12节 Python中使用BeautifulSoup解析http报文:使用select方法快速定位内容
一、 引言
在《第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问》和《第14.11节 Python中使用BeautifulSoup解析http报文:使用查找方法快速定位内容》介绍了通过属性和查找方法定位HTML报文的内容的方法,除了这两种方法还有一种方法就是通过使用CSS选择器的语法找到tag,关于css选择器老猿在此不进行介绍,大家可以自行查找文档了解,老猿推荐W3School 的《CSS 选择器参考手册》。其实不了解也问题不大,本节的内容绝大部分还是很好理解的。
二、 select方法
语法调用:
select(selector,namespace=None,limit=None,**kwargs)语法释义
1)参数selector为css选择器,关于CSS 选择器,请参考W3School 的《CSS 选择器参考手册》,具体应用方法请见第三部分;
2)namespace:为一个映射css选择器名字空间到名字空间URIs的字典,老猿对css选择器没有研究过,使用时一般用缺省参数
3)limit:限制查找到的内容个数,缺省不限制个数;
4)kwargs:老猿没有查到相关资料,暂时不使用;
5)返回值为一个列表,里面包含所有满足条件的html元素。
关于select的参数,官网上没有列出,只在举例中使用了第一个参数,老猿是通过help查出来的参数。不过也说明其他参数不重要,我们也就不关注了。
三、 使用select的几种场景及方法
- 本部分的html文本及BeatifulSoap对象定义如下:
>>> html='''<html><head><title>老猿Python</title></head>
<body><div>
<h1 id="l1" class='t1' name="line1">老猿Python第1行</h1>
<h2 id="l2" class='t2' name="line2">老猿Python第2行</h2>
<h3 id="l3" class='t3' name="line3">老猿Python第3行</h3>
<div>
<h1 id="l4" class='t1' name="line4">LaoYuanPython第1行</h1>
<h2 id="l5" class='t2' name="line5">LaoYuanPython第2行</h2>
<h3 id="l6" class='t3' name="line6">LaoYuanPython第3行</h3>
</div>
</div></body></html>'''
>>> soup = BeautifulSoup(html, 'lxml')
>>>
- 查找某个名称的所有标签
要查找某个名称的所有标签,直接在BeatifulSoap对象下调用select,语法如下:
select(“标签名”)
如:
>>> soup.select('h1')
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>]
>>>
soup.select(‘h1’)效果与soup.find_all(‘h1’)相同。当然调用也可以从某个标签对象发起,这样是查的该标签对象下所有指定名称的标签。如:
>>> soup.div.div.select('h1')
[<h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>]
>>>
- 查找某个符合要求的所有标签
这个功能是“查找某个名称的所有标签”的扩展,也可以说“查找某个名称的所有标签”是本功能的一个特例。
语法为:
select(“css选择器”)
其中css选择器可以是如下内容:
1)标签名:等同于功能“查找某个名称的所有标签”
2)css类名:查找css类名为指定类名的所有html元素,语法为:
select(”.类名”)
注意类名前有个小数点
>>> soup.select('.t1')
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>]
>>>
3)属性名:查找存在属性为指定属性名的所有html元素,语法为:
select(”[属性名]”),如:
>>> soup.select('[class]')
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h3 class="t3" id="l3" name="line3">老猿Python第3行</h3>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>, <h2 class="t2" id="l2" name="line2">LaoYuanPython第2行</h2>, <h3 class="t3" id="l3" name="line3">LaoYuanPython第3行</h3>]
>>> soup.select('[name]')
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h3 class="t3" id="l3" name="line3">老猿Python第3行</h3>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>, <h2 class="t2" id="l2" name="line2">LaoYuanPython第2行</h2>, <h3 class="t3" id="l3" name="line3">LaoYuanPython第3行</h3>]
>>>
4)属性名+属性值查找:
>>> soup.select("[name='line5']")
[<h2 class="t2" id="l5" name="line5">LaoYuanPython第2行</h2>]
>>>
属性名值支持首字符串(使用^符号)匹配、尾字符串匹配(使用$符号)和包含字符串(使用*符号)匹配:
>>> soup.select("[name^='line']") #属性名+属性值开始字符串匹配
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h3 class="t3" id="l3" name="line3">老猿Python第3行</h3>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>, <h2 class="t2" id="l5" name="line5">LaoYuanPython第2行</h2>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
>>> soup.select("[name$='e5']") #属性名+属性值尾字符串匹配
[<h2 class="t2" id="l5" name="line5">LaoYuanPython第2行</h2>]
>>> soup.select("[name*='e5']") #属性名+属性值字符串包含内容匹配
[<h2 class="t2" id="l5" name="line5">LaoYuanPython第2行</h2>]
>>>
>>>
5)id名:查找id为指定名字的所有html元素,语法为:
select(”#id名”),如:
>>> soup.select('#l1')
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h1 class="t1" id="l1" name="line1">LaoYuanPython第1行</h1>]
>>>
6)叠加标签:
上述第2-4种方法,可以在选择器前面叠加一个标签名,就可以实现在上述方法的基础上叠加需要满足标签名的要求的查找条件,如:
>>> soup.select("h1.t1") #标签名+css类名
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
>>> soup.select("h1[name]") #标签名+属性名
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
>>> soup.select("h1[name=line1]") #标签名+属性名+属性值
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>]
>>> soup.select("h1#l4") #标签名+id值
[<h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
注意以上条件组合时,如果标签和后面叠加内容要求是同一个标签下的内容时,标签和后面内容不能加空格,如果加了空格,就是到标签下的子标签中查找后面叠加内容的元素。如:
>>> soup.select("h1#l4") #查找标签为h1且id为l4的标签
[<h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
>>> soup.select("h1 #l4") #查找父标签为h1且其下id为l4的子孙标签
[]
>>> soup.select("div #l4") #查找父标签为div且其下id为l4的子孙标签
[<h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
>>>
属性名查找支持模糊查找
>>> soup.select("h3[class$='3']") #标签名+属性名1+属性名+属性值尾字符匹配
[<h3 class="t3" id="l3" name="line3">老猿Python第3行</h3>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
>>> soup.select("h1[name^='line']") #标签名+属性名+属性值开始字符串匹配
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
>>>
4. 在某个标签下查找所有子孙节点标签
其中的selector参数填写父标签和子标签名,使用空格分隔,selector参数的实参内容为:“父标签名 子孙标签1 … 子孙标签n”,每个标签鉴间用空格分隔。父标签可以从HTML报文的任意一个标签开始,子孙标签1可以是父标签的直接子标签也可以是更低层次的子孙标签,后面每个子孙标签都是前一个标签的直接子标签或更低层次的子孙标签。如:
>>> soup.div.div.select('h1')
[<h1>LaoYuanPython第一行</h1>]
>>> soup.select('body h2')
[<h2>老猿Python第二行</h2>, <h2>老猿Python第三行</h2>, <h2>LaoYuanPython第二行</h2>, <h2>LaoYuanPython第三行</h2>]
>>> soup.select('body div h2 ')
[<h2>老猿Python第二行</h2>, <h2>老猿Python第三行</h2>, <h2>LaoYuanPython第二行</h2>, <h2>LaoYuanPython第三行</h2>]
>>> soup.select('body div div h2 ')
[<h2>LaoYuanPython第二行</h2>, <h2>LaoYuanPython第三行</h2>]
5. 在某个标签下查找所有直接子标签
其中的selector参数填写父标签和子标签名,使用大于号分隔,selector参数的实参内容为:“父标签名>子孙标签1> …> 子孙标签n”,每个标签鉴间用大于号分隔。父标签可以从HTML报文的任意一个标签开始,子孙标签1必须是父标签的直接子标签,后面每个子孙标签都是前一个标签的直接子标签。如:
>>> soup.select('body>div>h2 ')
[<h2>老猿Python第二行</h2>, <h2>老猿Python第三行</h2>]
>>>
6. 查找解析的某个标签后面的兄弟标签
此功能与《第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问》、《第14.11节 Python中使用BeautifulSoup解析http报文:使用查找方法快速定位内容
》介绍的兄弟标签有所不同。
语法如下:
BeautifulSoup.select(“css选择器1 ~ css选择器2”)
该方法是查找css选择器1确认的首个标签后,到该标签后面内容中的兄弟标签中查找满足css选择器2的兄弟标签。如:
>>> soup.select("[name^='line']")
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h3 class="t3" id="l3" name="line3">老猿Python第3行</h3>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>, <h2 class="t2" id="l5" name="line5">LaoYuanPython第2行</h2>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
>>> soup.select("[name^='line'] ~ [class='t2']")
[<h2 class="t2" id="l2" name="line2">老猿Python第2行</h2>, <h2 class="t2" id="l5" name="line5">LaoYuanPython第2行</h2>]
>>>
7. 一次查找多个标签
要查找的标签间用逗号分隔,如:
>>> soup.select("h3.t3,h1#l4")
[<h3 class="t3" id="l3" name="line3">老猿Python第3行</h3>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
>>>
四、 select查找的总结
上面罗列了很多html元素通过css选择器来查找的场景,老猿总结select的使用方法如下:
1、 select可以通过只传递一个”css选择器”参数来调用;
2、 ”css选择器”参数可以支持嵌套多个子选择器组合,每个子选择器的构成方式包括:
1)单个标签;
2)单个属性;
3)单个属性值;
4)单个css类;
5)单个id;
6)以上内容的组合,组合时多个组合项之间不能有空格,如:
>>> soup.select("h1#l1[name$='1'].t1")#标签+id+属性尾字符匹配+CSS类的组合查找
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>]
>>> soup.select("h1#l1[name$='1'] .t1") #css类前有空格,会认为是两个子选择器,且相互之间是祖先节点与孙节点的关系
[]
>>>
且这些子选择器每相邻的两个子选择器之间可以支持不同的关系组合,包括:
1)父子关系组合:不同的选择器之间用大于号(>)分隔,后一个选择器查找html元素时只能到前一个选择器定位的标签内的直接子节点内查找。如:
>>> soup.select("body>div>h1[class='t1']")
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>]
>>>
2)子孙关系组合:不同的选择器之间用空格分隔,后一个选择器查找html元素时只能到前一个选择器定位的首个标签的子孙节点内查找。如:
>>> soup.select("body div>h1[class='t1']")
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h1 class="t1" id="l4" name="line4">LaoYuanPython第1行</h1>]
>>>
3)兄弟关系组合:不同的选择器之间用波浪线(~)分隔,后一个选择器查找html元素时只能到前一个选择器定位的首个标签的后面的兄弟节点内查找。如:
>>> soup.select("div>h1~#l3") #查找div节点的直接子节点h1的后面的id为l3兄弟节点
[<h3 class="t3" id="l3" name="line3">老猿Python第3行</h3>]
>>> soup.select("div h1~[class='t3']") #查找div节点的子孙节点h1后面的class属性值为t3的兄弟节点
[<h3 class="t3" id="l3" name="line3">老猿Python第3行</h3>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
>>>
4)并列关系组合:不同的选择器之间用逗号(,)分隔,查找时两个选择器之间是或的关系,即只要满足任意一个选择器的条件都认为符合查找要求。
>>> soup.select("div>h1#l1,div>div>h3.t3")
[<h1 class="t1" id="l1" name="line1">老猿Python第1行</h1>, <h3 class="t3" id="l6" name="line6">LaoYuanPython第3行</h3>]
>>>
五、 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方法快速定位内容的更多相关文章
- 第14.11节 Python中使用BeautifulSoup解析http报文:使用查找方法快速定位内容
一. 引言 在<第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问>介绍了BeautifulSoup对象的主要属性,通过这些属性可以访 ...
- 第14.10节 Python中使用BeautifulSoup解析http报文:html标签相关属性的访问
一. 引言 在<第14.8节 Python中使用BeautifulSoup加载HTML报文>中介绍使用BeautifulSoup的安装.导入和创建对象的过程,本节介绍导入后利用Beauti ...
- 第14.8节 Python中使用BeautifulSoup加载HTML报文
一. 引言 BeautifulSoup是一个三方模块bs4中提供的进行HTML解析的类,可以认为是一个HTML解析工具箱,对HTML报文中的标签具有比较好的容错识别功能.阅读本节需要了解html相关的 ...
- 第7.26节 Python中的@property装饰器定义属性访问方法getter、setter、deleter 详解
第7.26节 Python中的@property装饰器定义属性访问方法getter.setter.deleter 详解 一. 引言 Python中的装饰器在前面接触过,老猿还没有深入展开介绍装饰 ...
- 第8.23节 Python中使用sort/sorted排序与“富比较”方法的关系分析
一. 引言 <第8.21节 Python中__lt__.gt__等 "富比较"("rich comparison")方法用途探究>和<第8.2 ...
- 第14.9节 Python中使用urllib.request+BeautifulSoup获取url访问的基本信息
利用urllib.request读取url文档的内容并使用BeautifulSoup解析后,可以通过一些基本的BeautifulSoup对象输出html文档的基本信息.以博文<第14.6节 使用 ...
- 第9.12节 Python中其他文件操作方式
一. 引言 本章老猿主要介绍了Python 内置io模块的文件操作相关功能,其实除了内置io模块可以进行文件操作外,Python的不同模块还提供了多种文件操作方式,下面简单将这些模块和方法介绍一下. ...
- 第9.10节 Python中IO模块其他文件操作属性和方法简介
本文中所有案例中的fp都是使用open函数打开文件返回的一个文件对象,为了节省篇幅,大部分没有提供文件打开的代码. 一. 文件是否关闭的属性 属性名:closed 功用:判断文件是否关闭 示例: &g ...
- 第8.27节 Python中__getattribute__与property的fget、@property装饰器getter关系深入解析
一. 引言 在<第7.23节 Python使用property函数定义属性简化属性访问的代码实现>和<第7.26节 Python中的@property装饰器定义属性访问方法gette ...
随机推荐
- Tensorflow学习---argmax中axis问题
一:argmax中axis问题 https://blog.csdn.net/qq575379110/article/details/70538051/ 总之:axis=0/1不是行/列关系 test ...
- Netty源码解析 -- 零拷贝机制与ByteBuf
本文来分享Netty中的零拷贝机制以及内存缓冲区ByteBuf的实现. 源码分析基于Netty 4.1.52 Netty中的零拷贝 Netty中零拷贝机制主要有以下几种 1.文件传输类DefaultF ...
- MySQL全面瓦解10:分组查询和聚合函数
概述 相信我们经常会遇到这样的场景:想要了解双十一天猫购买化妆品的人员中平均消费额度是多少(这可能有利于对商品价格区间的定位):或者不同年龄段的化妆品消费占比是多少(这可能有助于对商品备货量的预估). ...
- 处理request信息的ngx_http_process_request
在处理完http的头部信息后 然后在 处理request-body信息ngx_http_process_request-------- -----------ngx_http_process_req ...
- rbd的增量备份和恢复
前言 快照的功能一般是基于时间点做一个标记,然后在某些需要的时候,将状态恢复到标记的那个点,这个有一个前提是底层的东西没用破坏,举个简单的例子,Vmware 里面对虚拟机做了一个快照,然后做了一些系统 ...
- 【javascript】掌握ES6-10,附xmind思维导图,每个知识点备注说明案例,请享用
前段时间一直想掌握ES6-10,陆陆续续花了1个月的时间,自学了ES6-10的新知识点,大部分都是非常实用的,花了2天时间整理思维导图 思维导图已上传博客园,请享用. ES6-10思维导图xmind ...
- 痞子衡嵌入式:JLink Script文件基础及其在IAR下调用方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是JLink Script文件基础及其在IAR下调用方法. JLink可以说是MCU开发者最熟悉的调试工具了,相比于其他调试器(比如DAP ...
- [USACO14JAN]Ski Course Rating G
题目链接:https://www.luogu.com.cn/problem/P3101 Slove 这题我们可以尝试建立一个图. 以相邻的两个点建边,边的权值为两个点高度差的绝对值,然后把边按照边权值 ...
- mysql密码问题
这位老哥的: 版权声明:本文为CSDN博主「csdn-华仔」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/ ...
- .NET 5 ORM 八大实用技巧 干货 - SqlSugar ORM
介绍 sqlsugar已经在第一时间完美兼容.NET5并且已经有人在使用了, 很多人都担心用了开源框架遇到问题无法解决,导致前功尽弃,使用SqlSugar你大可放心,除了有详细文档和几年的大量用户积累 ...