目录
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,你可以方便的查找节点、获取想要的数据
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()