JSONPATH实战案例:爬取异步加载的网站
目标
要求
-
初始化Excel文件:创建一个Excel工作簿,并激活一个工作表。
-
循环翻页获取数据:循环页码(从1到11),每页请求一次数据。
-
获取数据: 通过循环页码(1到11)实现翻页
-
数据解析:使用 jsonpath 提取标题和链接,通过遍历列表提取来源(处理了可能缺失来源的情况)。
-
数据保存:使用 openpyxl 将数据保存到Excel文件,并在每次添加数据后立即保存(确保即使中途出错,已获取的数据不会丢失)。
-
进度显示:在发送请求时打印当前页码(“正在爬第{}页”)。
代码
import requests
from openpyxl import workbook
from jsonpath import jsonpath
# 创建excel表格
wb = workbook.Workbook()
# 激活表格
ws = wb.active
# 写入表头
ws.append(['标题', '链接', '来源'])
# 网站地址
base_url = 'https://news.qq.com/'
# 实际请求网站数据地址
url = 'https://i.news.qq.com/web_feed/getHotModuleList'
# 定义请求头伪装浏览器
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0',
'referer':base_url,
'cookie':'pgv_pvid=7622756160; fqm_pvqid=44c32a9d-18ca-40ed-a2be-327ad57a652d; RK=1CM9Q0f6T4; ptcz=4e326bb414b4a5d892e869265bd8da31e2856720f7e28bbe212297cd945da48a; eas_sid=p157P5R2C7n6V4m3J0u2E2K7C7; _qimei_q36=; _qimei_h38=c71da2112b10dfb9ba387b890200000df1930f; pac_uid=0_APnhf3b4pxn9j; omgid=0_APnhf3b4pxn9j; current-city-name=hubhg; _qimei_fingerprint=674a0f722eaaa0aa689780d401e35a7b; _qimei_uuid42=1971e0001061001bb2f05c295768815dc8879d2fd1; lcad_appuser=4C5B9CEDCA719B60; lcad_Lturn=463; lcad_LPLFturn=549; lcad_o_minduid=I-qZrc2TJuXjGHzNIKC34kfw4kCTI4o_; lcad_LPSJturn=8; lcad_LBSturn=840; lcad_LVINturn=323; lcad_LDERturn=665',
'content-type':'application/json;charset=UTF-8',
'accept':'application/json, text/plain, */*'
}
page = 1
while True:
# 写请求体里面的参数
data ='{"base_req":{"from":"pc"},"forward":"2","qimei36":"0_APnhf3b4pxn9j","device_id":"0_APnhf3b4pxn9j","flush_num":%d,"channel_id":"news_news_top","item_count":20}'%page
# 发送请求,获取响应
response = requests.post(url, data, headers=headers)
dict_data = response.json()
# 进行判断,如果没有dict_data里面没有data数据,就无需继续爬取
try:
dict_data['data']
except Exception as e:
print('没有内容,无需进行爬取')
break
# 解析内容
# 标题列表
title_list = jsonpath(dict_data,'$..title')
# 详情页url列表
url_list = jsonpath(dict_data,'$..share_url')
# 获取实际来源列表
base_chl_name_list = jsonpath(dict_data,'$..chl_name')
print(f'正在爬取第1页,获取到标题数量为{len(title_list)}------详情页数量为{len(url_list)}-------来源数量为{len(base_chl_name_list)}')
# 处理实际的来源,防止写入文件的时候产生错位
# 先获取对象data
data_medias = dict_data['data']
# 来源列表
chl_name_list = []
for data_media in data_medias:
# 获取来源
try:
chl_name = data_media['media_info']['chl_name']
if chl_name:
# 如果有来源则追加来源值
chl_name_list.append(chl_name)
else:
# 反之追加没有来源字符串
chl_name_list.append('没有来源')
except Exception as e:
# 程序报错也一样追加
chl_name_list.append('没有来源')
# 写入文件本身
for title,urldetial,chl_name_detial in zip(title_list,url_list,chl_name_list):
ws.append([title,urldetial,chl_name_detial])
print(f'写入{title}完成')
print('-'*50)
wb.save('腾讯新闻.xlsx')
page += 1