«

数据提取

时间:2023-2-27 23:54     作者:wen     分类: Python


响应内容的分类

结构化响应内容

  1. json字符串(高频出现)
    • json模块
    • re模块
    • jsonpath模块
  2. xml字符串(低频出现)
    • 可以用re、lxml模块提取数据

非结构化响应内容

  1. html字符串
    • 可以用re、lxml模块提取数据

xml和html区别

xml是一种可扩展标记语言,样子和html很像,功能更专注于传输和存储数据

html是一种超文本标记语言,功能专注于显示数据

jsonpath模块

使用场景:多层嵌套的复杂字典直接提取数据

安装:
pip install jsonpath
使用方法:

from jsonpath import jsonpath
ret = jsonpath(a,'jsonpath语法规则字符串')

jsonpath语法:

$               -----------> 根节点
.               -----------> 选择子节点
..              -----------> 选择子孙节点(不考虑层级)
[]              -----------> 选择子节点/选择数组索引
[,]             -----------> 选择多个字段
@               -----------> 代表当前选中的节点(和条件过滤一起使用)
[?(过滤条件)]    ------------> 通过条件过滤数据
*               ------------> 通配符,表示匹配所有

案例:

from jsonpath import jsonpath
data = {'code': 200,
        'data': [
            {'photo': 'https://static-image.xfz.cn/1454046552_487.png', 'create_time': '2016-01-29 13:49:13',
             'link': 'http://www.ehoutai.com/', 'uid': 7, 'name': '易后台'},
            {'photo': 'https://static-image.xfz.cn/1454046135_474.png', 'create_time': '2016-01-29 13:42:15',
             'link': 'http://www.sanjieke.com/', 'uid': 4, 'name': '三节课'},
            {'photo': 'https://static-image.xfz.cn/1454046053_122.png', 'create_time': '2016-01-29 13:40:53',
             'link': 'https://www.aliyun.com/', 'uid': 1, 'name': '阿里云'},
            {'photo': 'https://static-image.xfz.cn/1454047318_361.png', 'create_time': '2016-01-29 14:01:59',
             'link': 'http://xmanlegal.com/', 'uid': 8, 'name': '未来法律'}]}

data2 = {'code': 0,
         'msg': 'OK',
         'data':
             {'id': 10006043,
              'leave_amount': -422500.0,
              'mobile_phone': '13449960188',
              'reg_name': '小柠檬',
              'reg_time': '2021-01-01 22:03:39.0',
              'type': 1,
              'token_info':
                  {'token_type': 'Bearer',
                   'expires_in': '2021-01-07 12:32:52',
                   'token': 'eyJhbGciOiJIUzUxMiJ9.eyJtZW1iZXJfaWQiOjEwMDA2MDQzLCJleHAiOjE2MDk5OTM5NzJ9.W_wi-NFjJMa3NZF9BOv_j0DvdSRhP7ncMrLfDdpM7HPpW01Afh7Gn6MAQXAFsS0Wge2BUlXAxLNTEv2RO3w-Ow'}},
         'copyright': 'Copyright Abby © 2017-2020 腾讯公司 All Rights Reserved'
         }

token = jsonpath(data2, "$..token")
print(token)

# 选择子节点
code = jsonpath(data2, "$.code")  # ==  jsonpath(data2, "$[code]")
print(code)

# 通过索引选择列表中的数据
code = jsonpath(data, "$.data[0]")  # ==  jsonpath(data, "$[data][0]")
print(code)
code1 = jsonpath(data, "$.data[1].name")  # == jsonpath(data, "$.data[1][name]")
print(code1)

# 选择多个字段
code2 = jsonpath(data, "$.data[1][name,link,]")  # ==  jsonpath(data, "$.data[1].name,link")
print(code2)
code3 = jsonpath(data2, "$.data[id,mobile_phone,type]")  # == jsonpath(data2, "$.data.[id,mobile_phone,type]")
print(code3)

# 通过过滤条件
res1 = jsonpath(data, "$.data[?(@.uid==4)]")  # == jsonpath(data, "$[data][?(@.uid==4)].name")
# print(jsonpath(data, "$.data[?(@.name=='阿里云')]"))
print(res1)
res2 = jsonpath(data, "$.data[?(@.uid==4)][name]")  # == jsonpath(data, "$.data[?(@.uid==4)].name") # == jsonpath(data, "$[data][?(@.uid==4)].name")
# print(jsonpath(data, "$.data[?(@.uid > 7)][name]"))
print(res2)

lxml模块

lxml模块可以利用XPath规则语法,来快速的定位HTM\XML文档中特定元素以及获取节点信息(文本内容、属性值)
XPath(XML Path Language)是一门在HTM\XML文档中查找信息的语言,可用来在HTM\XML文档中对元素和属性进行遍历。
文档
提取xml、html中的数据需要lxml模块和xpath语法配合使用
xpath语法:

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。
text() 选取文本

案例:

/html/head/title/text() # 选择标题内容
//text/text()
//link/@href # 选择属性

节点修饰语法:

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[contains(text(),"一页")] 选取 bookstore 元素的所有 book 元素,且文本中包含一页的

选择未知节点的语法:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
//title[@*] 选取所有带有属性的 title 元素。

选取若干路径:

路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
//title | //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

lxml模块安装:

pip install lxml

from lxml import etree
html = etree.HTML(text)
res_list = html.xpath("xpath语法规则字符串")

lxml模块中etree.tostring函数的使用

from lxml import etree

# 将html源码创建成element对象
html = etree.HTML(content)
# etree.HTML() 能够自动补全html缺失的标签
etree.tostring(html)

标签: 爬虫