ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用Excel Power Query自动抓取天天基金网基金净值,告别手动更新

用Excel Power Query自动抓取天天基金网基金净值,告别手动更新 做基金定投的朋友应该都干过这样的事收盘后打开天天基金网一只一只基金找历史净值复制粘贴到 Excel 里做统计。基金数量少还能忍要是手里有十几只或者想跑个回测、算个定投收益光手动更新净值就能耗掉一晚上而且很容易漏一天、复错一格。我之前也一直被这个问题折磨直到把 Power Query 这套自动抓取流程跑通才发现每天更新净值这件事根本不用亲自动手。今天就把这套用 Excel Power Query 抓天天基金网数据、自动更新基金净值的完整流程写出来从最基础的抓取到常见错误修复都覆盖争取让新手也能一次跑通。这个方案不需要学 Python不依赖独立软件只要你的 Excel 里有 Power Query 组件就行。它解决的核心问题有三个每天手动查净值太费时间、复制粘贴容易出错、历史数据积累起来没法复盘。我建议所有做基金定投、基金研究或者帮家里老人管理多只基金账户的朋友都把这个流程搭起来。下面我把思路、实操步骤和踩过的坑全部拆开讲。1. 这活儿为什么值得自动化先聊聊我的使用场景1.1 手动更新基金净值的痛我一开始是用最笨的办法记录净值打开天天基金网找到基金代码点历史净值然后从网页表格里框选数据复制到 Excel再把“单位净值”那一列反复确认格式。后来我管了 8 只基金还帮朋友管了 5 只总共 13 只。每晚更新一次每只基金平均要花 3 分钟一天就是 40 分钟。遇到页面加载慢、Excel 日期格式识别错乱时间直接翻倍。更麻烦的是手动维护数据很容易出连续性错误。比如某天忘了复制漏掉一行Excel 里用公式算收益时就会错位。等你发现的时候可能已经基于错误数据做了一周的统计。数据自动化不只是省时间更重要的是保证数据的完整性和一致性。1.2 为什么是 Power Query 而不是 Python 爬虫 / VBA很多人会想写个 Python 爬虫不就行了吗我之前也写过一个小脚本用 requests 请求天天基金网的接口把结果存成 CSV再导入 Excel。问题是这个方案有维护成本电脑上必须装 Python 环境脚本依赖的第三方库版本一变就报错还得手动定时运行。对于日常工作流来说太重了。VBA 也能操作 HTTP 请求和 HTML 解析但写起来并不舒服尤其是解析网页表格和嵌套 JSON 时代码会变得很冗长而且不同 Excel 版本对 VBA 的网络请求支持也不一致。Power Query 的优势在于几点原生内置于 Excel不需要额外开发环境。自带“从 Web”抓取可解析 HTML 表格也可处理 JSON。查询建立后可以通过“刷新”一键更新还能设置定时刷新。整个数据清洗过程可以点选完成也可以写少量 M 语言做复杂处理。所以虽然 Python 对于专业爬虫场景更灵活但在“Excel 里维护基金净值数据”这个特定场景下Power Query 是最合适的方案。我后来把所有基金数据都迁到了 Power Query再也不用每天打开脚本、复制文件了。2. 核心设计思路先把抓取链路拆清楚2.1 天天基金网的数据结构长什么样抓取之前先得搞明白天天基金网的净值数据到底放在哪里。天天基金有一个专门展示历史净值的接口地址类似http://fund.eastmoney.com/f10/F10DataApi.aspx?typelsjzcode110022page1per49这个接口返回的是 HTML 片段里面是一个标准表格包含“净值日期、单位净值、累计净值、日增长率”这些字段。它的优点是非常规整Power Query 可以直接识别表格缺点是单页最多返回 49 条数据想拿完整历史需要翻页。天天基金另外还有一个 JSON 接口地址类似https://api.fund.eastmoney.com/f10/lsjz?fundCode110022pageIndex1pageSize100startDateendDate这个接口返回的是真正的 JSON 数据字段更全比如分红信息、申购状态、赎回状态等。它需要带 Referer 请求头才能访问在 Power Query 里可以通过 Headers 参数来设置。两条链路各有适用场景。如果你想快速实现推荐先掌握 HTML 表格接口如果你希望后续扩展更多字段、批量抓取多只基金建议直接学会 JSON 接口。2.2 两条抓取路线的取舍在实操之前我帮你梳理一下两条路线的区别对比项F10DataApi HTML 接口api.fund JSON 接口新手友好度高从 Web 自动识别表格中需要手动解析 JSON是否需要请求头不需要需要 Referer返回字段丰富度基础净值字段够用更完整含分红、费率等稳定性日常使用稳定偶尔被限流相对稳定建议降低刷新频率批量处理可以处理但翻页逻辑稍复杂更灵活适合参数化函数我做经验总结时有个习惯先跑通最简单的链路再逐步升级。所以下面会先讲 HTML 接口的抓取再讲 JSON 接口的玩法。两者可以共用同一个“更新净值”的场景你只需要选一条顺手的主流方案用起来。2.3 自动更新的实现逻辑Power Query 能做到“自动更新”核心靠的是查询连接和 Excel 的刷新机制。简单说你通过 Power Query 建立查询后数据会形成一个“连接”这个连接就像一个水龙头打开一次就按照你写好的规则从天天基金网取数、转换、加载到工作表。之后只需刷新连接就能重新执行一遍取数流程。自动更新有两种方式打开文件时刷新打开 Excel 文件就自动拉取当天最新净值。定时刷新设置每隔多少分钟刷新一次适合开着表格盯数据的场景。对大多数基民来说每天收盘后净值一般在晚上 8 到 10 点更新。你完全可以中午打开文件时手动刷一次或者配置“打开文件时刷新”就可以了不用真的一直开着表。3. 手把手实操用 Power Query 把净值抓回来3.1 准备工作确认 Power Query 环境开始之前先确认你的 Excel 里有 Power Query。不同版本的位置不太一样Excel 2016及以上Windows功能在“数据”选项卡的“获取和转换”区域。Excel 2013需要先安装 Power Query 加载项安装后会在“加载项”选项卡里出现。Excel for Mac部分版本没有完整 Power Query 功能建议在 Windows 环境操作或者用网页版 Excel。如果打开 Excel 找不到 Power Query先检查“文件 - 选项 - 加载项 - COM 加载项”里是否禁用了相关插件。这里是个常见坑我之前遇到过一次明明电脑装了 Excel却找不到“自 Web”按钮最后发现是加载项被安全软件禁用了。3.2 方案A从 F10DataApi HTML 接口抓取新手友好这个方案适合第一次上手逻辑最简单。操作步骤如下第一步新建一个空白的 Excel 工作簿然后点“数据 - 获取数据 - 自其他源 - 自 Web”。第二步在弹出的对话框里输入 URL。以易方达沪深300ETF联接基金 110022 为例http://fund.eastmoney.com/f10/F10DataApi.aspx?typelsjzcode110022page1per49sdateedate接着点“确定”。Power Query 会访问这个地址并尝试把返回的 HTML 解析成表格。第三步在“导航器”窗口里你会看到页面解析出来的多个表格大部分是这个接口返回的脚本内容我们只需要那个包含“净值日期、单位净值、累计净值、日增长率”的表格。选中它点右下角的“转换数据”。第四步进入 Power Query 编辑器后先调整列名和数据类型。把“净值日期”改成日期类型“单位净值”和“累计净值”改成小数“日增长率”改成小数。Power Query 有时候会把增长率识别成文本因为接口里可能是“1.2345”这样的字符串需要用“替换值”把结尾的百分号去掉再转数字如果列里显示 null先保留并稍后处理。第五步在“主页”选项卡里点“关闭并加载”。这时会让你选加载方式选择“表”把数据加载到新工作表。如果你的基金历史超过 49 条需要在 M 公式里加上翻页逻辑。我常用的方式是先从page1per49拿第一页然后观察返回数据里的总页数再通过List.Generate把每一页的内容都请求回来合并。不过对于大部分只需要近几个月数据的场景49 条可能不够可以用per500吗实测这个接口单个请求的 per 参数不是无限大设置为 49 比较稳超过会被服务器拒绝。想要更长时间跨度可以改 URL 里的sdate和edate参数按时间段分批请求后追加。如果你觉得翻页麻烦那就直接看方案B。JSON 接口一次可以返回 100 条甚至更多处理起来更直接。3.3 方案B从 JSON 接口抓取更稳定、适合扩展这个方案我目前主力在用。它不用翻页返回的是结构化 JSON解析后能拿到更完整的字段。流程稍微复杂一些但搞明白以后你会觉得比 HTML 接口更顺手。第一步打开“数据 - 获取数据 - 自其他源 - 空白查询”。这会进入 Power Query 编辑器。第二步在编辑器顶部的“视图”里打开“高级编辑器”用下面的 M 公式请求 JSON 数据并解析let 基金代码 110022, 请求头 [Headers [#Referer http://fund.eastmoney.com/, #User-Agent Mozilla/5.0]], 接口地址 https://api.fund.eastmoney.com/f10/lsjz?fundCode 基金代码 pageIndex1pageSize100startDateendDate, 源 Web.Contents(接口地址, 请求头), 解析JSON Json.Document(源), content 解析JSON[Content], data content[Data], lsjz列表 data[LSJZList], 转表 Table.FromList(lsjz列表, Splitter.SplitByNothing(), null, null, ExtraValues.Error), 展开 Table.ExpandRecordColumn(转表, Column1, {FSRQ, DWJZ, LJJZ, JZZZL}, {净值日期, 单位净值, 累计净值, 日增长率}) in 展开这里我解释一下每部分的作用。Web.Contents是 Power Query 里用来发起 HTTP 请求的函数后面的Headers参数给它带上 Referer模拟从天天基金网页面发起的请求否则接口可能返回空白或 403。Json.Document把返回的 JSON 字符串转成对象。后面的content - data - LSJZList是按照接口返回的嵌套结构逐层取数据。这个层级结构不需要死记你可以在浏览器地址栏直接访问接口地址用浏览器自带的格式化功能查看。展开后通常你会得到四列数据FSRQ净值日期DWJZ单位净值LJJZ累计净值JZZZL日增长率字段名可能随接口更新略有变化但大多数情况下就是这四个。如果你发现展开后缺少某个字段回去检查 JSON 里实际返回的列名即可。展开完成后按需要修改数据类型再“关闭并加载”到工作表。这样单只基金的历史净值就抓回来了。3.4 把数据加载到 Excel 并设置自动刷新数据加载到工作表后还不能叫“自动更新”。你需要配置一下刷新方式。点击表格区域任意位置然后打开“数据 - 查询和连接”。在右侧“查询和连接”面板中找到刚才建立的查询右键点击选择“属性”。在“使用情况”选项卡里勾选“刷新此连接的时间间隔”并输入一个分钟数我建议 5 到 10 分钟。这里要提醒一句天天基金网毕竟是公开网站刷新频率太频繁容易被临时限制日常场景别低于 5 分钟。同时我还建议勾选“打开文件时刷新数据”。这样一来你每天打开 Excel 工作簿它就会自动把最新净值拉回来你只需要看一眼数据是否更新不用再逐只基金去查了。如果你不想让打开文件时等太久可以在“数据 - 查询选项”里调整后台刷新设置。不过对我个人来说等待几秒钟换取当天准确数据是非常划算的。4. 多只基金批量更新参数化查询的高级玩法4.1 先建一张“基金代码参数表”单只基金能抓了多只基金自然也能抓。关键是不要复制粘贴十几遍查询而是利用 Power Query 的参数化查询把“基金代码”当作输入一次批量刷新所有基金。第一步在 Excel 里新建一个工作表专门用来放基金代码和备注。比如基金代码基金简称备注110022易方达沪深300ETF联接A主力持仓005827易方达蓝筹精选定投003096中欧医疗健康A观察注意这张表里的“基金代码”必须存成文本格式不能是数字。因为好多基金代码是以 0 开头数字类型会自动去掉前导零比如 003096 会变成 3096那接口就查不到数据了。4.2 写一个自定义查询函数接下来在 Power Query 里写一个接收基金代码并返回净值表的函数。新建一个空白查询输入以下 M 公式(基金代码 as text) as table let 请求头 [Headers [#Referer http://fund.eastmoney.com/, #User-Agent Mozilla/5.0]], 接口地址 https://api.fund.eastmoney.com/f10/lsjz?fundCode 基金代码 pageIndex1pageSize100startDateendDate, 源 Web.Contents(接口地址, 请求头), 解析JSON Json.Document(源), data 解析JSON[Content][Data], lsjz列表 data[LSJZList], 转表 Table.FromList(lsjz列表, Splitter.SplitByNothing(), null, null, ExtraValues.Error), 展开 Table.ExpandRecordColumn(转表, Column1, {FSRQ, DWJZ, LJJZ, JZZZL}, {净值日期, 单位净值, 累计净值, 日增长率}) in 展开然后将这个查询命名为GetFundHistory。注意Power Query 里函数名不能用中文和空格我这里的“基金代码”参数名是中文但函数名是英文实际用起来没问题。如果你担心兼容性参数名也建议改成英文比如fundCode然后引用处同步改为GetFundHistory(fundCode)。4.3 批量调用并展开数据有了函数之后再用一次查询把股票代码参数表和函数连接起来。新建一个查询目标是“基金代码参数表”然后在“添加列”选项卡里选择“调用自定义函数”。在弹出的窗口中函数选择GetFundHistory参数选择基金代码列。这样每一行基金代码都会生成一个对应的净值表。调用完成后每一行里会多出一列“GetFundHistory”这样的表格列。你只需要点这个列标题右边的展开按钮把要展开的字段勾选上系统就会把所有基金的历史净值纵向拼接在一起每一行都自带对应的基金代码。最后把查询结果加载到工作表并设置刷新。以后只要更新参数表或者想新增基金往表里加一行代码刷新查询新基金的净值就会自动拉进来。整个过程逻辑清楚维护起来也方便。不过这里要提醒一个实测经验如果基金数量超过 20 只同时刷新十几个请求很容易触发天天基金网的反爬机制导致部分查询失败。我的做法是控制单次抓取频率把刷新间隔设置在 10 分钟以上。有时还会把基金代码表拆成两个查询错峰刷新避免一次请求太多。5. 常见错误修复与排坑实录这一部分是我最想重点写的因为方案本身不复杂但在具体操作中会遇到各种意想不到的问题。我把实际踩过的坑以及群里朋友问得最多的问题整理成了表格。错误现象常见原因解决方法刷新时提示“无法刷新连接”隐私级别设置阻止了外部数据访问文件 - 选项 - 隐私 - 勾选“忽略隐私级别”返回 400 请求错误JSON 接口缺少 Referer 或请求头不对在 Web.Contents 中补上 Referer并检查 URL 参数中文乱码接口返回的是 GBK 编码Power Query 识别成 UTF-8用 Web.Page 替代 Web.Contents或使用 Text.FromBinary 指定编码找不到“Content”或“Data”字段接口返回了错误页面或临时被限流先用浏览器访问接口确认返回正常再检查请求头有些净值字段变成 null当日未更新或停牌数据为空不用特殊处理后续刷新会补上或筛选过滤日期列变成文本格式网页返回的是文本Power Query 自动识别失败用“更改数据类型”手动改成日期打开 Excel 后很久才刷新完成基金代码太多或者刷新间隔太短减少单批基金数量调大刷新间隔5.1 抓回来的数据全是乱码怎么办这个问题主要出现在直接用Web.Contents请求 HTML 接口时。天天基金网的 F10DataApi 返回的是 GBK 编码Power Query 的自动检测有时会选错编码。解决思路有两条第一条改用Web.Page函数而不是Web.Contents。Web.Page会按照网页声明的编码来做一次解析通常能正常取出表格。第二条如果数据源是 JSON 接口它返回的是 UTF-8一般不会乱码。但如果确实遇到乱码可以在 M 公式里用Text.FromBinary(源, 936)强制转码其中 936 表示 GBK。这个方法不是万能的但能解决一部分遗留问题。我个人的建议是优先切换接口。JSON 方案除了更干净扩展性也更好没必要硬啃 HTML 接口的编码问题。5.2 刷新时提示“无法刷新连接”或“(400) 请求错误”这种情况十有八九是请求头的问题。天天基金网的 JSON 接口会检查发起请求的来源如果请求头里没有Referer服务器会拒绝返回数据。在 Power Query 中你需要在Web.Contents第二个参数里传入一个包含 Headers 的记录。我常用的请求头是[Headers [#Referer http://fund.eastmoney.com/, #User-Agent Mozilla/5.0]]这相当于告诉服务器“我是从天天基金网页面过来请求的”。加上之后400 错误基本就能解决。如果还不行打开浏览器开发者工具复制实际发起请求时的完整请求头再补进 Power Query。还有一种情况是“无法刷新连接”这种和隐私级别有关。Power Query 默认阻止外部数据源之间的组合尤其是当你把基金代码参数表和网络请求组合在一起时它会保守地拒绝刷新。解决办法是打开“文件 - 选项 - 隐私”勾选“忽略隐私级别”。这个选项适合自己本地文件使用如果是公司电脑请先确认信息安全要求。5.3 JSON 解析报错“找不到成员”这个报错通常是因为接口返回的不是正常的 JSON而是一段错误提示文本或者验证页面。最直接的排查方式是把接口地址复制到浏览器里访问一下。如果浏览器能看到正常的 JSON 数据说明问题出在 Power Query 的请求头或参数上如果浏览器也看不到那就是接口地址、基金代码或者参数名写错了。有时候接口未更新或者基金代码输入错误也会导致返回内容为空。建议在 M 公式里先把Web.Contents的结果取出来点击查看返回值再做后续解析。我在调试时经常把源这个步骤单独列出来用“表格预览”先看原始输出这样可以很快定位是网络问题还是解析问题。5.4 自动刷新总是失败或卡住Power Query 刷新失败通常不是某一个原因而是多个因素叠加。我把排查顺序列一下先网络如果是公司网络需要确保能直接访问外部网站。再请求头确认带没带 Referer。后频率如果之前手动刷新太频繁可能被服务器临时限制等几分钟再试。最后看日志Power Query 查询编辑器底部的“查询依赖项”或“数据源设置”能看到一些线索。另外在 Excel 里如果同时开了多个工作簿其中一张表正在刷新另外一张表可能显示“正在计算”而暂时无法复制粘贴。我遇到过好几次用户以为 Excel 坏了实际只是 Power Query 刷新时临时占用了资源。等它刷完操作就恢复正常。如果你在刷新过程中发现复制粘贴没反应可以按 Esc 取消刷新或者等待右下角状态栏的正在刷新提示消失。5.5 数据加载后日期、净值为文本格式Power Query 从网页拿到的数据默认是文本即使显示上很像日期和数字也需要手动指定数据类型。单击列标题左边的类型图标改成“日期”或“小数”。改完后再重新加载Excel 里的单元格格式才会正常。如果你希望每次刷新后都保持格式强烈建议在 Power Query 查询的最后几个步骤里加上Table.TransformColumnTypes。这样无论是手动刷新还是定时刷新系统都会自动执行类型转换不会每次刷新后又变回文本。我还见过一种情况净值列里有“--”或“暂无”这样的占位符导致类型转换报错。遇到这种情况可以在转换类型之前先用“替换值”把特殊文本替换成 null或者用“筛选行”把无效行去掉。6. 后续扩展建议数据拿回来之后还能做什么流程跑通只是第一步。净值数据进入 Excel 后你可以基于它做很多有价值的分析。我个人最常用的是两个方向第一个是定投收益跟踪。把每期定投的日期和金额记录下来再用基金净值去折算确认份额最后汇总出当前持仓收益和总收益率。这个计算用 Excel 公式就能实现关键是数据基础要准。有了 Power Query 自动更新的净值整个表格每周打开就能看到最新收益。第二个是回测和定投策略对比。比如下载某只指数基金近三年净值然后手动模拟“每周一定投”和“每月初定投”的差异。Power Query 可以做数据清洗历史净值够长计算公式跑起来也不难。我的建议是先把数据存成“日期、单位净值、累计净值、日增长率”的标准格式后续任何基金都能复用同一套分析模型。我还建议把接口返回的“日增长率”列保留下来不要只留单位净值。很多收益统计公式都依赖增长率尤其是不同净值精度导致的复利计算偏差用增长率反推会更准。最后再分享一个实用小技巧在设置自动刷新时可以给每一个查询起清楚的名字比如110022_易方达沪深300而不要让它默认叫“查询1”“查询2”。因为后期基金数量多了查询名不直观容易找错对象。命名规范虽然是小细节但在实际维护中能省很多事。我自己的流程现在长这样每天收盘后打开基金工作簿点一下刷新所有基金的净值自动更新到最新。用到的工具就是 Excel 自带的 Power Query不需要打开网页不需要手工复制也不用额外维护脚本。整个过程跑下来我把每天 40 分钟的机械操作压缩成了不到 10 秒钟。现在我把这个流程分享出来就是希望被基金净值表格折腾过的人都可以早点解脱。
返回列表