BeautifulSoup4和JsonPath
文章目录
- Json解析
BeautifulSoup4
- BeautifulSoup可以从HTML、XML中提取数据,目前BS4在持续开发。
- 官方中文文档https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
- 安装
-
pip install beautifulsoup4
- 导入:
from bs4 import BuautifulSoup
- 初始化:
- BeautifulSoup(markup="",features=None)
- markup,被解析对象,可以是文件对象或者html字符串
- feature指定解析器
- return:返回一个文档对象
- 可以不指定解析器,就依赖系统已经安装的解析器库了。
解析器 | 使用方法 | 优势 | 劣势 |
Python标准库 | BeautifulSoup(markup,“html.parser”) | Python的内置标准库 执行速度适中 文档容错能力强 | Python 2.7.3、3.2.2前 的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup,“lxml”) | 速度快 文档容错能力强 | 需要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup,[“lxml”,“xml”]) BeautifulSoup(markup,“xml”) | 速度快 唯一支持XML的解析器 | 需要安装C语言库 |
html5lib | BeautifulSoup(markup,“html5lib”) | 最好的容错性 以浏览器的方式解析文档 生成HTML5格式的文档 | 速度慢 不依赖外部扩展 |
- BeautifulSoup(markup,“html.parser”)使用Python标准库,容错差且性能一般。
- BeautifulSoup(markup,“lxml”)容错能力强,速度快。需要安装系统C库。
- 推荐使用lxml作为解析器,效率高。
- 需要手动指定解析器,以保证代码在所有运行环境中解析器一致。
- 使用下面内容构建test.html使用bs4解析它
- 四种对象
- BeautifulSoup将HTML文档解析成复杂的树型结构,每个节点都是Python的对象,可分为4种:
- BeautifulSoup、Tag、NavigableString、Comment
- BeautifulSoup对象:代表整个文档。
- Tag对象:对应着HTML中的标签。有2个常用的属性:
- name:Tag对象的名称,就是标签名称
- attrs:标签的属性字典
- 多值属性,对于class属性可能是下面的形式,
<h3 class="title highlight">python高级班</h3>
这个属性就是多值({“class”:[“title”,“highlight”]}) - 属性可以被修改、删除
- BeautifulSoup.prettify() #带格式输出解析的文档对象(即有缩进的输出),注意:直接输出BeautifulSoup会直接输出解析的文档对象,没有格式。
- BeautifulSoup.div #输出匹配到的第一个div对象中的内容,返回对象是bs4.element.Tag类型
- BeautifulSoup.h3.get(“class”) #获取文档中第一个标签为h3对象中class属性值
- 注意:我们一般不使用声明这种方式来操作HTML,此代码时为了熟悉对象类型
- NavigableString
- 如果只想输出标记的文本,而不关心标记的话,就要使用NavigableString.
- 注释对象:这就是HTML中的注释,它被BeautifulSoup解析后对应Comment对象。
遍历文档树
- 在文档树中找到关心的内容才是日常的工资,也就是说如何遍历树中的节点。使用上面的test.html来测试
- 使用Tag
- soup.div可以找到从根节点开始查找第一个div节点,返回一个Tag对象
- soup.div.p说明从根节点开始找到第一个div后返回一个Tag对象,这个Tag对象下继续找第一个p,找到返回Tag对象
- soup.p返回了文字“字典”,而不是文字“bottom"说明遍历时深度优先,返回也是Tag对象
- 遍历直接子节点
- Tag.contents #将对象的所有类型直接子节点以列表方式输出
- Tag.children #返回子节点的迭代器
- Tag.children #等价于Tag.contents
- 遍历所有子孙节点
- Tag.descendants #返回节点的所有类型子孙节点,可以看出迭代次序是深度优先
- 遍历字符串
- 在前面的例子中,soup.div.string返回None,是因为string要求soup.div只能有一个NavigableString类型子节点,也就是这样
<div>only string</div>
。 - Tag.string #获取Tag下的string对象,如果多余1个结点返回None
- Tag.strings #返回迭代器,带多余的空白字符。所有的string对象
- Tag.stripped_strings #返回,会去除多余空白字符
- 遍历祖先节点
- BeautifulSoup.parent #获取根节点的父结点,必定返回None,根节点没有父结点
- Tag.parent #获取第一个Tag的父结点
- Tag.parent.parent.get(“id”) #获取第一个tag的父结点的父结点的id属性
- Tag.parents #获取Tag节点的所有父结点,由近及远
- 遍历兄弟节点
- Tag.next_sibling #第一个Tag元素的下一个(下面)兄弟节点,注意:可能是一个文本节点
- Tag.previous_sibling #第一个Tag元素之前的兄弟节点(上面),注意:可能是一个文本节点
- Tag.next_siblings #获取Tag元素的下面的所有兄弟节点
- 遍历其他元素
- Tag.next_element #是下一个可被解析的对象(字符串或tag),和下一个兄弟节点next_sibling不一样
- Tag.next_elements #返回所有下一个可被解析的对象,是个可迭代对象。
搜索文档树
- find系有很多分发,请执行查询帮助https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/#id25
-
find_all(name=None,attrs={},recursive=True,text=None,limit=None,**kwargs)
#立即返回一个列表
- name参数:官方称为fiter过滤器,这个参数可以是一下
- 字符串:一个标签名称的字符串,会按照这个字符串全长匹配标签名
print(soup.find_all('p'))
#返回文档中所有p标签 - 正则表达式对象:按照"正则表达式对象"的模式匹配标签名
- 列表:或关系查找列表中的每个字符串
- True或None,则find_all返回全部非字符串节点、非注释节点,就是Tag标签类型
- 函数
- 如果使用以上过滤器还不能提取想要的节点,可以使用函数,此函数仅只能接收一个参数。
- 如果这个函数返回True,表示当前节点配置;返回False则是不匹配。
- 示例:找出所有class属性且有多个值的节点(测试html中符合这个条件只有h3标签)
- keyword传参
- 使用关键字传参,如果参数名不是find系函数已定义的位置参数名,参数会被kwargs收集并被当做标签的属性来搜索。
- 属性的传参可以是字符串、正则表达式对象、True、列表。
- css的class的特殊处理
- class是Python关键字,所以使用
class_
。class是多值属性,可以匹配其中任意一个,也可以完全匹配。
- attrs参数
- attrs接收一个字典,字典的key为属性名,value可以是字符串、正则表达式对象、True、列表。可以多个属性
- text参数
- 可以通过text参数搜索文档中的字符串内容,接受字符串、正则表达式对象、True、列表
- limit参数:显示返回结果的数量
- recursive参数
- 默认是递归搜索所有子孙节点,如果不需要请设置为False
- 简化写法
- find_all()是非常常用的方法,可以简化省略掉
- find方法
-
find(name,attrs,recursive,text,**kwargs)
- 参数几乎和find_all一样。
- 找到了,find_all返回一个列表,而find返回一个单值,元素对象。
- 找不到,find_all返回一个空列表,而find返回一个None。
CSS选择器
- 和JQuery一样,可以使用CSS选择器来 查找节点
- 使用soup.select()方法,select方法支持大部分CSS选择器,返回列表。
- CSS中,标签名直接使用,类名前加
.
点号,id名前加#
井号。
- BeautifulSoup.select(“css选择器”)
- 获取文本内容
- 搜索节点的目的往往是为了提取该节点的文本内容,一般不需要HTML标记,只需要文字
- bs4.element.Tag#string源码
Json解析
- 拿到一个Json字符串,如果想提取其中的部分内容,就需要遍历了。在遍历过程中进行判断。
- 还有一种方式,类似于XPath,叫做jsonPath。
- 安装
pip install jsonpath
- 官网https://goessner.net/articles/JsonPath/
XPath | JsonPath | 说明 |
| | 根元素 |
| | 当前节点 |
| | 获取子节点 |
| 不支持 | 父节点 |
| | 任意层次 |
| | 通配符,匹配任意节点 |
| 不支持 | json中没有属性 |
| | 下标操作 |
| | XPath是或操作,JSONPath allows alternate names or array indices as a set. |
不支持 | | 切片 |
| | 过滤操作 |
不支持 | | 表达式计算 |
| 不支持 | 分组 |
- 综合示例,使用豆瓣电影的热门电影的Jsonhttps://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=10&page_start=0