Python爬虫教程 - 100天从新手到大师(06Day)


1. 异步加载

含义:向网站进行一次请求,一次只传部分数据。如:有些网页不需要点击下一页,其内容也可以源源不断地加载。
url表面没有发生变化的情况下,加载出来了其它的数据(内容) 动态数据 url > 一个响应 一份响应数据

js代码 触发 鼠标的点击 鼠标的滑动 ajax异步加载

url页面没有发生改变的情况下,通过鼠标的滑动,点击加载出来的动态数据包,都是存在于XHR里面

2. 豆瓣异步加载数据案例

目标Url : https://movie.douban.com/typerank?type_name=%E5%96%9C%E5%89%A7&type=24&interval_id=100:90&action=

"""
演示豆瓣电影异步加载数据的抓取 动态数据
"""

import requests

if __name__ == '__main__':
    # 1.确认目标url
    url_ = 'https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&start=0&limit=20'

    # 用户代理的构造
    headers_ = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
    }

    # 2.发送网络请求,获取响应对象
    response_ = requests.get(url_, headers=headers_)
    str_data = response_.text

    # 4.保存
    with open('douban_01.json', 'w', encoding="utf-8") as f:
        f.write(str_data)

翻页:

"""
演示翻页
"""
"""
翻页url的规律 
第一页:https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&start=0&limit=20
第二页:https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&start=20&limit=20
第三页:https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&start=40&limit=20
经过分析:url start参数是以20的等差数列进行的翻页
"""

import requests
import time
if __name__ == '__main__':
    pages_ = int(input('请输入你想要抓取的页数:'))
    for i in range(pages_):  # 3  0 1 2
        # 1.确认url
        url_ = f'https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&start={i*20}&limit=20'

        # 用户代理的构造
        headers_ = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
        }

        # 2.发送网络请求,获取响应对象
        response_ = requests.get(url_, headers=headers_)
        str_data = response_.text

        # 4.保存
        with open(f'douban_第{i+1}页.json', 'w', encoding="utf-8") as f:
            f.write(str_data)

        time.sleep(2)  # 每爬取一页就等待2秒 符合正常人的操作 降低请求频率,避免被反爬

3. 数据结构分类

字符串类型(文本类型的数据)

爬虫抓取到的文本数据
结构化数据
结构比较规范
json xml(极其的稀少)

json格式数据的特点

1.最外层要么是一个列表一样的[],要么是一个字典一样的{}
2.json数据的引号必须是双引号
3.末尾元素,不写逗号
4.没有注释

作用:填充网页
提取json类型的数据,需要一个第三方库 jsonpath pip install jsonpath -i https://pypi.doubanio.com/simple

正则: 效率高,但难度大
bs4:难度小,但效率较低

数据提取
json >> jsonpath >> pip install jsonpath -i https://pypi.doubanio.com/simple
html >> xpath >> python里面使用lxml这个库 去实现xpath语法
pip install lxml -i https://pypi.doubanio.com/simple

xml和html的区别

1.xml是严谨的结构化数据
2.xml数据的容器,作用仅仅是保存数据,是一个数据的载体
3.html是一种呈现方式

4. json格式数据

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互。
后端提供了json格式的数据给前端(浏览器),django python 前端 json格式的数据 如果想用python控制,处理json格式的数据,格式的转化操作 转化成我们python能够处理的数据格式 字典

4.1 json格式和python格式相互转换

python >> json: json.dumps()

json >> python: json.loads()

python里面的字典数据类型 >> json数据 (前端才能够进行数据的填充)

import json  # 原生自带

if __name__ == '__main__':
    # python数据 > 字典
    dict_data = {
        "name": "李华",
        "age": 18
    }
    print(type(dict_data), dict_data)

    # python类型的字典数据 转为 json类型的数据 默认使用的是ascii编码 ensure_ascii=False 显示出中文
    json_data = json.dumps(dict_data, ensure_ascii=False, indent=10)  # indent=3 每一个键值对的缩进的空格数据
    print(type(json_data), json_data)  # json字符串 本质是一个字符串
import json  # 原生自带

if __name__ == '__main__':
    # python数据 > 字典
    dict_data = {
        "name": "李华",
        "age": 18
    }

    # python类型的字典数据 > json类型的数据 默认使用的是ascii编码 ensure_ascii=False 显示出中文
    json_data = json.dumps(dict_data, ensure_ascii=False)  # indent=3 每一个键值对的缩进的空格数据
    print(type(json_data), json_data)  # json字符串 本质是一个字符串

    # json类型的数据 > python类型的字典数据  才能够处理从前端交互过来的json数据
    python_data = json.loads(json_data)
    print(type(python_data), python_data)

4.2 json文件跟python的转换

"""
json文件跟python的转换
"""
# import json
# python格式的数据 >> json文件

# # 构造一个字典
# dict_data = {
#     'name':'wawa',
#     'age':18
# }
#
# # 文件对象
# file_obj = open('json_01.json','w')
#
# # 少了一个s 就是直接跟json文件打交道
# json.dump(dict_data,file_obj,ensure_ascii=False)

import json

# json文件 >> python格式的数据
# 1.文件对象
file_obj = open('json_01.json', 'r')

python_data = json.load(file_obj)
print(python_data, type(python_data))
file_obj.close()

"""
注意: json.dumps()和json.dump(),json.loads()和json.load()的区别
有s的是直接和json数据打交道;没有s的是和json文件打交道

python数据 >> json数据 : json.dumps(python数据,ensure_ascii=False)
python数据 >> json文件 :json.dump(python字典,json文件对象,ensure_ascii=False)

json数据  >> python数据:json.loads(json数据)
json文件  >> python数据:json.load(json文件对象)

"""

4.3 jsonpath提取json数据

pip install jsonpath -i https://pypi.doubanio.com/simple

JsonPath为Json文档提供了解析能力,通过使用JsonPath,你可以方便的查找节点、获取想要的数据

JsonPath用法详解

5. 实战案例

爬取 豆瓣电影悬疑片的电影名称,电影评分,上映时间,排名 并保存到本地

import requests  # 抓取模块
import jsonpath  # 解析模块
import csv  # 保存模块
import time  # 时间模块


def get_json_data(i):
    
    url_ = f"https://movie.douban.com/j/chart/top_list?type=10&interval_id=100%3A90&action=&start={i * 20}&limit=20"
    # 构造用户代理
    headers_ = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"
    }

    # 发送网络请求,获取响应对象
    response_ = requests.get(url_, headers=headers_)

    # 把json数据转换成python数据
    python_data = response_.json()

    return python_data


def parse_json_data(python_data):
    # 电影名称列表
    title_list = jsonpath.jsonpath(python_data, '$..title')

    # 电影评分列表
    score_list = jsonpath.jsonpath(python_data, '$..score')

    # 上映时间
    release_date_list = jsonpath.jsonpath(python_data, '$..release_date')

    # 排名
    rank_list = jsonpath.jsonpath(python_data, '$..rank')

    # 把每部电影的数据都统一放在一个元组中再转换成为一个列表

    li = zip(title_list, score_list, release_date_list, rank_list)

    return li


def save_data(li, i):
    # 保存
    with open(f'豆瓣悬疑片{i + 1}.csv', 'w', newline='') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(['电影名称', '电影评分', '上映时间', '排名'])
        for row in li:
            writer.writerow(row)

        time.sleep(2)  # 每爬取一页就等待2秒,符合正常人的操作 降低请求频率


def main():
    pages_ = int(input("请输入你想要抓取的页数:"))
    for i in range(pages_):
        save_data(parse_json_data(get_json_data(i)), i)


if __name__ == '__main__':
    main()

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值