金融数据获取:通过Ajax跳转的网页怎么爬?以东方财富基金净值数据为例

news2024/12/24 21:47:03

        你是否碰到过点击网站上的按钮或链接,网页数据进行了刷新,但浏览器上显示的网址却没有任何变化的情况,这其实就是利用Ajax跳转的网页。本期笔者将以东方财富网为例展示如何获取Ajax跳转的网页内容,本文主要内容如下:


目录

1. Ajax跳转的网页

2. Selenium模拟爬取

3. 寻找真实数据接口

4.代码实现


1. Ajax跳转的网页

        上一期的数据获取文章通过爬取网页上的交互式图表,获取了东方财富网上的基金净值数据,但有粉丝私信说这个数据并不全,东方财富只抽取了部分日期的净值数据进行了展示。本期笔者将通过另一种方法爬取所有的NAV数据。

        其实东财是有完整的历史净值数据的,但是一旦选择图一右上角成立以来的数据,东财就开始偷懒。可能是出于获得更快的网页响应速度,东财选择只抽取部分的净值数据进行展示。有时是在一个月中抽取一天,有时候是抽取两天。

 图一:东方财富网基金净值图表

         显然通过这种方式已经无法拿到所有完整数据了,但笔者很快就发现东财上另一个网址:

(000189)基金历史净值 ,这个网址通过表格的形式将所有历史数据展示出来,但这种表格的难点在于无论怎么点击下面的页数,浏览器上显示的网址都没有任何变化。如图二:

         图二:基金净值列表与浏览器网址

2. Selenium模拟爬取

        点击下一页,浏览器上显示的网址却没有任何变化,这其实就是Ajax跳转的网页,普通的通过解析浏览器网址已经失效。

        但这个本质上与js动态加载类似,都是需要某些事件触发才会刷新数据,并且浏览器网址还能保持不变。笔者之前出过一期selenium模拟爬虫,模拟爬虫用在这种网页上也是有效的,通过模拟点击网页的方式不断的获取后面的页数就可以不断地获取数据,但缺点是非常缓慢。

3. 寻找真实数据接口

        还有一种非常直接的思路:既然网站需要将数据展示出来,这中间就一定需要一个步骤——请求服务器上的数据,只要我们可以拦截到浏览器向服务器发送的真实请求就可以轻易破解。该方法的难点在于如何在这么多的请求中找到那个真实请求,网上其实有很多抓包工具可以解析然后搜索到那个请求。但笔者本次爬取的东方财富网较为简单,只需要打开网络监控,然后点击下一页就可以轻易获取到真实请求的地址。

        首先打开网页:(000189)基金历史净值 。等待网页刷新完成后再按F12,此时是没有任何请求的。

        重点来了,点击第二页按钮,这时就会发现网络监控捕获到请求,如下图的第三个红框:

 图三:获取请求的步骤

        点击第三个红框就会展示出该请求的详细信息,第4个红框即是净值数据的接口地址。

        就这样,什么抓包工具都不需要,轻松且愉快就获得了接口地址

        下面是笔者获取到的地址信息:

http://api.fund.eastmoney.com/f10/lsjz?callback=jQuery18301815712066237849_1685791444537&fundCode=000189&pageIndex=2&pageSize=20&startDate=&endDate=&_=1685791451115

        其中,fundCode参数是基金代码,pageIndex是第几页,pageSize是一页上返回多少条数据。下面就非常简单了,不断循环pageIndex参数就可以将所有数据全部拿下来。

4.代码实现

        因为这个接口是可以设置每页返回数据量的,这里可以设置一个大一些的数字,这样可以避免频繁请求给服务器造成压力,下面笔者将参数设置成500。下面也用到headers模拟请求技术,不明白的可以看笔者上一期数据获取文章。获取到网页数据后就是字符串的日常操作了,感觉没什么好讲解的,直接写成模块:

def craw_data(code, page_num): # 基金代码,页码
    url = "http://api.fund.eastmoney.com/f10/lsjz?callback=jQuery18308048793570706319_1685784091702&fundCode="+code+"&pageIndex="+page_num+"&pageSize=500&startDate=&endDate=&"
    headers = {"Referer": "http://fundf10.eastmoney.com/"}
    re = requests.get(url, headers = headers)

    df = re.text
    if len(df) > 300: # 获取内容超过300个字符一般说明成功获得数据了
        df = df.split('LSJZList":[{"')[1].split('}],"FundType"')[0] # 提取数据主体
        df = df.replace('null', '"null"') # 添加“”号方便后续拆分
        df = df.replace('""', '"null"') # 空值统一替换为null

        data_set = []
        for data in df.split('"},{"'):
            data = data.split('","')
            row = {}
            for i in data:
                i = i.split('":"')
                row[i[0]] = i[1]
            data_set.append(row)
        data_set = pd.DataFrame(data_set)
        data_set = data_set[["FSRQ", "DWJZ", "LJJZ", "JZZZL"]]
        data_set.columns = np.array(["日期", "单位净值", "累计净值", "日增长率"])
        data_set["日增长率"] = data_set["日增长率"].replace("null", 0)
        data_set[["单位净值", "累计净值", "日增长率"]] = data_set[["单位净值", "累计净值", "日增长率"]].astype("float") # 转化为浮点类型数据
        data_set.set_index("日期", inplace=True)
        return pd.DataFrame(data_set)
    else: # 没有获得数据
        return pd.DataFrame()

        下面循环调用,加入一个判断条件,如果返回的空数据集,说明所有数据都爬取完了,停止循环:

code = "000165"
nav_data = pd.DataFrame()
for page_num in range(1, 1000): # 一般不太可能超过1000页
    data_set = craw_data(code, str(page_num))
    if len(data_set) != 0:
        nav_data = pd.concat([nav_data, data_set], axis=0)
    else: # 停止循环
        break
    print("正在获取{}页, 共获取{}条数据\r".format(page_num, len(nav_data)), end="")

        运行后获取数据如下:

	单位净值	累计净值	日增长率
日期			
2023-06-02	2.1610	3.5660	3.5660
2023-06-01	2.1440	3.5490	3.5490
2023-05-31	2.1430	3.5480	3.5480
2023-05-30	2.1530	3.5580	3.5580
2023-05-29	2.1510	3.5560	3.5560
...	...	...	...
2013-10-25	0.9980	0.9980	0.9980
2013-10-18	1.0030	1.0030	1.0030
2013-10-11	1.0040	1.0040	1.0040
2013-09-30	1.0000	1.0000	1.0000
2013-09-27	1.0000	1.0000	1.0000
2345 rows × 3 columns

        可以看到,笔者成功获取了完整的净值数据,共2345条数据。

        只要有所有的基金代码列表,这个程序可以将所有的基金数据全部拿到,但笔者建议最好加入一些随机暂停模块,防止封IP。。。

        最后展示一下获取到的净值走势:

nav_data = nav_data[::-1]
nav_data["累计净值"].plot()

         运行得图四:

         图四:累计净值走势

5. 系列往期速览

数据获取系列往期文章
专栏名称文章传送门
金融数据获取获取网站交互式图表背后的数据
当爬虫遇上要鼠标滚轮滚动才会刷新数据的网页
Fama-French及PSM
Grinold Kroner(GK)模型(本期)
增速g的测算
PE指标平滑
PE Band

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/606225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MyBatis(多表查询,动态SQL的使用)

目录 多表查询 查询文章详情 查询一个用户底下的所有文章 动态SQL的使用 if 标签 trim 标签 where 标签 set 标签 foreach 标签 多表查询 现在有俩张表,一张是文章表,一张是用户表.如下: 查询文章详情 我们现在想查询得到一张表,表里面的内容和文章表大多一致,只是要在…

银行从业资格证(初级) 5天零基础拿证攻略【个人经历,亲测】

我的科目:《法律法规》、《个人理财》 方法 直接做真题,做真题错题总结归纳。 教材可买可不买,时间不够可以不看教材。 可以买天一金融的真题汇编,它附赠一个考点整理的小册子。 一定要自己整理知识框架。 看个人习惯选择网上做…

chatgpt赋能python:Python列表中随机抽取6个元素的简单方法

Python列表中随机抽取6个元素的简单方法 在Python编程中,列表是一种常用的数据类型,它允许我们存储和操作一系列数据。有时候,我们需要从列表中随机抽取一些元素,比如从一组名字中随机选择几个人参加抽奖等。本文将介绍如何使用P…

MIT 6.824 lab distributed system 分布式系统

https://youtu.be/cQP8WApzIQQ 概念 为什么需要分布式系统? high performanceparallelism:分布式系统可以实现CPU、内存、硬盘的并行运行fault tolerancephysical:security / isolated 分布式系统的困难 concurrency:各个并行的…

【unity小技巧】使用贝塞尔曲线实现导弹随机攻击敌人,也可以用于拾取物品

文章目录 先看效果代码实现1.导弹代码2.玩家生成导弹代码3.玩家挂载代码4.导弹挂载代码先看效果 代码实现 1.导弹代码 记得配置敌人为enemy标签 using System.Collections; using System.Collections.Generic; using

Nautilus Chain:独特且纯粹的创新型 Layer3

以 Layer3 架构为主要特点的模块化公链 Nautilus Chain 即将在近期上线主网,这也进一步引发了行业关于 Layer3 的讨论。 实际上,在2022年以太坊的创始人 Vitalik 提出了三大目标:Layer2 用于扩展,Layer3 用于定制功能,…

Transformer模型原理—论文精读

文章目录 前言模型架构Encoder和DecoderEncoderDecoder AttentionFFNEmbeddings和Positional EncodingEmbeddingsPositional Encoding 总结 前言 今天来看一下Transformer模型,由Google团队提出,论文名为《Attention Is All You Need》。论文地址。 正如…

Openwrt_XiaoMiR3G路由器_刷入OpenWrt

刷入Openwrt之前请保证小米R3G路由器已经刷入Breed控制台固件。 刷入Breed请参考: Openwrt_XiaoMiR3G路由器_刷入Breed固件 路由器具体配置参考 小米路由器3G参数 - 小米商城 既然要刷入OpwnWrt就需要线编译固件,使用lede的OpenWrt源码编译。 进入 …

K8S集群安装(二)

目录 1 安装说明.... 1 1.1 安装环境.... 1 1.2 生产环境可部署Kubernetes集群的两种方式.... 2 1.3 操作系统初始化配置.... 3 2 安装Docker/kubeadm/kubelet【所有节点】.... 4 2.1 安装Docker. 4 2.2 添加阿里云YUM软件源.... …

《Apollo 智能驾驶进阶课程》

来自 : https://www.bilibili.com/video/BV1G341117NQ/ https://apollo.baidu.com/ 主要学习资源如下: Apollo社区公众号,直接有整个视频教程的微信推文教程:链接一个CSDN博主记录的笔记: https://blog.csdn.net/qq_45…

08 redis经典五种数据类型及底层实现

redis是字典数据库KV键值对是什么 redis 是 key-value 存储系统,其中key类型一般为字符串,value 类型则为redis对象(redisObject)Redis定义了redisObjec结构体来表示string、hash、list、set、zset等数据类型 C语言struct结构体语法简介Redis 中每个对象…

【华为机试】死记硬背没思路?一般人我劝你还是算了吧

大家好,我是哪吒。 五月份之前,如果你参加华为OD机试,收到的应该是2022Q4或2023Q1,这两个都是A卷题。 5月10日之后,很多小伙伴收到的是B卷,那么恭喜你看到本文了,抓紧刷题吧。B卷新题库正在更…

Spring依赖注入解析

目录 依赖注入大致要点 依赖注入大致流程 Bean的预实例化 doGetBean createBean 完备Bean的创建过程 createBeanInstance populateBean 依赖注入大致要点 Spring在Bean实例的创建过程中做了很多精细化控制finishBeanFactoryInitialization方法里面的preInstantiateSing…

【计算机网络复习】第六章 局域网 LAN

局域网( LAN)概述 LAN的特点 • 覆盖范围小 房间、建筑物、园区范围 • 高传输速率 10Mb/s~1000Mb/s • 低误码率 10-8 ~ 10-11 • 拓扑:总线型、星形、环形 • 介质:UTP、Fiber、C…

6年测试经验之谈,为什么要做自动化测试?

一、自动化测试 自动化测试是把以人为驱动的测试行为转化为机器执行的一种过程。 个人认为,只要能服务于测试工作,能够帮助我们提升工作效率的,不管是所谓的自动化工具,还是简单的SQL 脚本、批处理脚本,还是自己编写…

智能优化算法:指数分布优化算法-附代码

智能优化算法:指数分布优化算法 文章目录 智能优化算法:指数分布优化算法1.指数分布优化算法1.1种群初始化1.2EDO开发1.3EDO探索 2.实验结果3.参考文献4.Matlab5.python 摘要:指数分布优化算法(Exponential distribution optimize…

全新好用的窗口置顶工具WindowTop

打开WindowTop软件,所有已打开的窗口都会在左上角出现一个置顶栏,点击置顶栏的置顶复选框即可置顶窗口或取消窗口。   在WindowTop软件的置顶栏一项里可以自由调整置顶栏的元素(包含增删位置)。   可改变置顶栏的外观&#x…

剖析ffmpeg视频解码播放:时间戳的处理

一、视频播放基础理论 1.1 视频编码和解码基础 视频编码和解码是视频播放的基础,理解它们的工作原理对于深入理解视频播放至关重要。在这一部分,我们将详细介绍视频编码和解码的基础知识。 视频编码(Video Encoding)是将原始视…

离散数学_十章-图 ( 5 ):连通性 - 上

📷10.5 图的连通性 1. 通路1.1 通路1.2 回路1.3 其他术语 2. 无向图的连通性2.1 无向图的连通与不连通2.2 定理2.3 连通分支 3. 图是如何连通的3.1 割点( 关节点)3.2 割边( 桥)3.3 不可分割图3.4 𝑘(&#…