第七天——ajax异步加载解析案例
一、演示爬取异步加载数据包
同步加载又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,要先执行完当前操作,再继续下一步的操作,因此停止了后续的文件加载(如图像)、渲染、代码执行。
就是要按照规定的步骤来一步一步执行
通俗来说:比如我们去超时买东西,你要先拿你需要购买的东西,再去收银台付钱
家餐厅吧来了5个客人,同步的意思就是说,来第一个点菜,点了个鱼,好, 厨师去捉鱼杀鱼,过了半小时鱼好了给第一位客人,开始下位一位客人,就这样一个一个来,按顺序来。
异步加载又叫非阻塞,浏览器在下载执行 js 同时,还会继续进行后续页面的处理。
异步: 就是来第一位客人,点什么,点鱼,给它一个牌子,让他去一边等吧,下一位客人接着点菜,点完接着点让厨师做去吧,哪个的菜先好就先端出来
异步加载 :url表面没有发生变化的情况下,加载出来了其他的数据(内容) 动态数据,动态数据一般是js代码触发,比如鼠标的点击和鼠标的滑动,js只是用来处罚ajax异步加载发送请求》》》动态数据)
https://www.douban.com/ =》电影=》排行=》喜剧=》
https://movie.douban.com/typerank?type_name=%E5%96%9C%E5%89%A7&type=24&interval_id=100:90&action=
1.1 preview
试想,如果我们需要的目标数据是异步加载的话,我们对某一个页面的url发起请求是否能够拿到相关的数据呢?明显是不可能的,例如上方的电影网站。
点击第一个包以及preview,可以看到,明明页面上有电影数据,但是preview(预览)里面却没有显示,这就证明在当前页面中我们需要的目标数据在当前页面中是一个异步加载的数据。也就是说目标数据和当前页面所在的url路径并不是同一个,所以如果我们代码中是对当前页面所在的url发起请求的话是不可能拿到异步加载的目标数据的。同样的,在查看response的时候一样是无法查看到目标数据的,前面第三章已经介绍过,preview就是基于response的内容进行渲染。
1.2 XHR
url页面没有发生改变的情况下, 通过鼠标的滑动 点击加载出来的动态数据包,
都是存在与XHR里面。分析响应头不难发现其响应类型是一个application/json类型,也就是说响应的数据是一个json串。
1.在XHR里面,一个数据包:20条数据(20部电影)
这样看数据是不是看不清楚,很混乱,那么我们借助工具来看
- 打开json.cn
- 复制response里面的数据
- 粘贴到最左边,然后回车
二、代码实现爬取异步加载数据包
2.1 异步加载数据案例
"""
演示豆瓣电影异步加载数据的抓取 动态数据
"""
import requests
# 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; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3870.400 QQBrowser/10.8.4405.400"
}
# 2.发送网络请求,获取响应对象
response = requests.get(url, headers=headers)
# 字符串类型
str_data = response.text
print(str_data)
with open('douban_01.json', 'w',encoding="utf-8") as f:
f.write(str_data)
2.1 异步加载数据翻页案例
1.在XHR里面,一个数据包:20条数据(20部电影)
2.滑动鼠标 触发了js的ajax请求,得到响应,多了一个数据包,
第一个数据包: 1-20部电影 页面 20的电影数据的加载
第二个数据包: 21-40部电影 页面
第三个数据包: 41-60部电影
"""
豆瓣异步加载数据翻页案例
"""
import time
import requests
"""
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
https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&start=60&limit=20
经过分析: url start参数以20的等差数列进行翻页
"""
pages = int(input("请输入你想要抓取的页数:"))
for i in range(pages):
a = i * 20
# 1.确认动态的url
url = f'https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&start={a}&limit=20'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3870.400 QQBrowser/10.8.4405.400"
}
# 2.发送网络请求,获取响应数据
response = requests.get(url, headers=headers)
# 3. 获取响应的字符串类型的数据
str_data = response.text
with open(f'douban_dynamic_0{i + 1}.json', 'w', encoding='utf-8') as f:
f.write(str_data)
# 优化:防止被识别爬虫
time.sleep(1.5) # 没爬取一页就等待1.5秒 符合正常人的操作 降低请求频率
三、某电影网站解析案例
获取 https://movie.douban.com/typerank?type_name=%E5%96%9C%E5%89%A7&type=24&interval_id=100:90&action= 的电影名和评分。
# 1.确定目标url
import json
import jsonpath
import requests
url = "https://movie.douban.com/j/chart/top_list?type=24&interval_id=100%3A90&action=&start=0&limit=20"
# 2.发送网络请求
# 2.1 实现User-Agent用户代理,隐藏爬虫身份。使用正常浏览器的身份
headers_ = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36"
}
# 2.2 发送网络请求,把用户代理User-Agent带上,参数名称固定headers
response = requests.get(url, headers=headers_)
# 字符串类型
str_data = response.text
# 3.解析提取数据
# 将json数据类型转换为python数据类型
python_data = json.loads(str_data)
# 获取电影名
title_data = jsonpath.jsonpath(python_data, '$..title') # 返回的是一个列表
# 获取评分
score_data = jsonpath.jsonpath(python_data, '$..score') # 返回的是一个列表
# 将电影名和评分存储到字典里面
# 定义一个拼接数据的字典
movie_dict = {}
for i in range(len(title_data)):
# {'电影名':评分}
movie_dict[title_data[i]] = score_data[i]
print(movie_dict)
# 4.转换为json数据并且存入json文件
with open("movie.json", 'w', encoding='utf-8')as f:
json.dump(movie_dict, f, ensure_ascii=False)