day2-json请求和xpath解析

json数据

1. json的作用

让不同编程语言之间可以进行有效的数据交流(几乎所有的高级语言都支持json数据格式)

2. 什么是json

一个有效的json有且只有一个数据,并且唯一的这个数据必须是json支持的类型的数据。

json支持的数据类型:
数字 - 直接写,例如:100、+23、-45、12.5、3e4
字符串 - 加双引号,只有双引号,例如:“yuting”、“重庆”、“abc\n123”
布尔 - 只有true和false两个值
空值 - null
数组(列表) - 相当于Python的列表: [元素1, 元素2, 元素3,…]
字典 - 键必须是字符串: {键1:值1, 键2:值2,…}

3. json数据解析

1) 如果通过requests发送请求得到的数据就是json数据,可以直接用响应.json()将json数据转换成Python数据。
2) 非json接口提供的json数据的解析。
系统模块:json -> 提供将json数据转换成Python数据,以及将Python数据转换成json数据两个功能。

json.loads(json格式的字符串) - 将json转Python,返回值的类型会因为字符串的内容不同而不一样。

json.dumps(python数据) - 将Python数据转换json格式的字符串,返回值是字符串。

说明:json格式的字符串 - 字符串的内容是json格式的数据,例如:‘100’、’“abc”’、’{“a”: 100}’
int、float、str、bool、list、dict、None、tuple - 可以转成json数据

import json
# json转换python
result = json.loads('100')
print(result, type(result))  # 100 <class 'int'>

result = json.loads('"abc"')
print(result, type(result))  # abc <class 'str'>

result = json.loads('{"a": 100}')
print(result, type(result))  # {'a': 100} <class 'dict'>

result = json.loads('[100, "abc", true, null]')
print(result, type(result))  # [100, 'abc', True, None] <class 'list'>

# python转json
result = json.dumps(100)
print(result, type(result))  # 100 <class 'str'>

result = json.dumps('abc')
print(result, type(result))    # "abc" <class 'str'>

result = json.dumps([100, 12.4, True, None, 'hello', [10, 'a'], {10: 20}, (100, 200)])
print(result, type(result))     # '[100, 12.4, true, null, "hello", [10, "a"], {"10": 20}, [100, 200]]'<class 'str'> 

获取多页数据

# https://movie.douban.com/top250?start=0&filter=
# https://movie.douban.com/top250?start=25&filter=
# https://movie.douban.com/top250?start=50&filter=

import requests


def get_html(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
    }
    r = requests.get(url, headers=headers)
    r.encoding = r.apparent_encoding
    return r.text


def get_all_data():
    for x in range(0, 226, 25):
        url = f'https://movie.douban.com/top250?start={x}&filter='
        get_html(url)

xpath数据解析

运行环境:from lxml import etree
lxml: 可以通过xpath的方法来解析html数据和xml数据

1. 创建树结构,获取根节点

etree.HTML(html代码) - 将html页面创建成一个树结构,并且返回树的根节点。

html_node = etree.HTML(open('files/网页.html', encoding='utf-8').read())
print(html_node)  # <Element h1 at 0x6718667980>

2. 根据路径获取指定标签

节点对象.xpath(路径) - 返回值是列表,列表中的元素就根据路径找到的所有的结果
1) 绝对路径 - /从根节点开始写全路径
注意:绝对的写法和查找方式跟前面谁去.xpath没有关系

h1_node = html_node.xpath('/html/body/div/h1')[0]
print(h1_node)      # <Element h1 at 0x1108cf500>

p_nodes = html_node.xpath('/html/body/div/p')
print(p_nodes)       # [<Element p at 0x10bab15c0>, <Element p at 0x10bab1600>]

div_node_2 = html_node.xpath('/html/body/div')[-1]

result = div_node_2.xpath('/html/body/div/p')
print(result)

2) 相对路径: ./路径、. ./路径
. 表示当前节点 (谁去.xpath,当前节点就是谁)
. . 表示当前节点的上层节点

result = html_node.xpath('./body/div/p')
print(result)       # [<Element p at 0x104edb780>, <Element p at 0x104edb7c0>]

result = div_node_2.xpath('./p/text()')
print(result)       # [<Element p at 0x10e542900>]

result = div_node_2.xpath('../div/h1/text()')
print(result)

3) 全局搜索: //
//路径

result = html_node.xpath('//img')
print(result)       # [<Element img at 0x10c9fa780>, <Element img at 0x10c9fa880>, <Element img at 0x10c9fa8c0>, <Element img at 0x10c9fa900>, <Element img at 0x10c9fa940>]

result = html_node.xpath('//div/img')
print(result)   # [<Element img at 0x10502b940>, <Element img at 0x105

3. 获取标签内容和标签属性

1) 标签内容:获取标签的路径/text()

result = html_node.xpath('//p')
print(result)       # [<Element p at 0x10b74b880>, <Element p at 0x10b74b8c0>, <Element p at 0x10b74ba40>, <Element p at 0x10b74b980>, <Element p at 0x10b74bb00>]

result = html_node.xpath('//p/text()')
print(result)       # ['什么都卖!', '可以购买的商品!', '泡面', '火腿肠', '可乐'

属性值:获取标签的路径/@属性名

lt = html_node.xpath('//img')
print(result)   # [<Element img at 0x108189a00>, <Element img at 0x108189b00>, <Element img at 0x108189980>, <Element img at 0x108189ac0>, <Element img at 0x108189b80>]

result = html_node.xpath('//img/@src')
print(result)   # ['https://img1.baidu.com/it/u=3160659086,3725745087&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img1.baidu.com/it/u=3160659086,3725745087&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img1.baidu.com/it/u=3160659086,3725745087&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500', 'https://img0.baidu.com/it/u=1309756832,682125188&fm=26&fmt=auto', 'https://img0.baidu.com/it/u=707176316,890856051&fm=26&fmt=auto']

4. 谓语

1) [N] - 获取第N个(同级中取第N个)

result = html_node.xpath('//p[1]/text()')
print(result)

result = html_node.xpath('//ul/li[2]/p/text()')
print(result)

2) [last()] - 取最后一个(同级最后一个)

result = html_node.xpath('//ul/li[last()]/p/text()')
print(result)

# [last()-1]  - 倒数第2个
# [last()-2]  - 倒数第3个
result = html_node.xpath('//ul/li[last()-1]/p/text()')
print(result)

# [position() < 3]  - (1, 2)获取前两个
# [position() <= 3]   - (1,2,3)获取前3个
# [position() > 1]   - 从第2开始取完
result = html_node.xpath('//ul/li[position()<=2]/p/text()')
print(result)

result = html_node.xpath('//ul/li[position()>1]/p/text()')
print(result)

3) 属性相关谓语
[@属性名=值] - 获取指定属性为指定值的标签

# 获取body下面第一个div中class获取为c1的p标签
result = html_node.xpath('./body/div[1]/p[@class="c1"]/text()')
print(result) # ['我是段落1', '我是段落3']

# 获取页面中id为p1的p标签
result = html_node.xpath('//p[@id="p1"]/text()')
print(result) # ['我是段落4']

result = html_node.xpath('//p[@class="c1"]/text()')
print(result) # ['我是段落1', '我是段落3', '我是段落6']

4. 通配符

# * - 通配符,表示所有类型的标签
# 获取class为c1所有标签
result = html_node.xpath('//*[@class="c1"]/text()')
print(result) # ['我是段落1', '我是段落3', '超链接1', '我是段落6']

result = html_node.xpath('./body/div[1]/*/text()')
print(result)  # ['我是段落1', '我是段落2', '我是段落3', '我是段落4', '我是段落5', '超链接1']

5. 分支

路径1|路径2 - 按照两种路径获取标签

result = html_node.xpath('./body/div[1]/a|./body/div[1]/p')
print(result)

xpath解析豆瓣

import requests
from lxml import etree


def get_html(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
    }
    r = requests.get(url, headers=headers)
    r.encoding = r.apparent_encoding
    return r.text


if __name__ == '__main__':
    result = get_html('https://movie.douban.com/top250')
    # 解析
    html_node = etree.HTML(result)
    all_li = html_node.xpath('//ol[@class="grid_view"]/li')
    # print(all_li)
    for li in all_li:
        name = li.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0]
        score = li.xpath('./div/div[2]/div[2]/div/span[@class="rating_num"]/text()')[0]
        print(score)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值