加入 PowerBI自己学 知识星球:下载源文件,边学边练;遇到问题,提问交流,有问必答。
需要从如下网站获取基金编码为004853的历史净值明细表,如果用PowerBI直接获取网页,只能得到第1页的20条数据。而且在这个网页表格里切换页码,网址不会发生变化,不能通过在网址上设置参数的方式来获取多页数据。
解决方案
通过后台API获取数据,但是这个API不允许直接获取数据,而且一次只能返回20条数据,因此简单的调整API参数比如pageSize每页条数获取数据,需要增加User_Agent,按页码多次获取数据。
操作步骤
STEP 1 在网页上点鼠标右键选择Inspect,在Sources中可以看到,数据来源有一个API,复制这个API地址。截图中有3个网址,是因为点过3个页码,缓存了3次数据。
STEP 2 将API地址粘贴到PowerQuery的从Web获取数据,报错。把这个API地址直接放到浏览器中,会发现其中的Data对应的是空值,这个API不支持直接获取数据。修改获取数据的代码,增加User_Agent,以用户方式获取数据,发现可以读取到较多数据。
= let
Headers = [
Referer = "https://fund.eastmoney.com/",
User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
],
Source = Web.Contents("https://api.fund.eastmoney.com/f10/lsjz", [
Query = [
fundCode = "004853",
pageIndex = "1",
pageSize = "20",
startDate = "",
endDate = ""
],
Headers = Headers
])
in
Source
STEP 3 双击返回的结果图标(JSN文件),默认会用Json.Document函数做解析,Data不空了,对应了Record记录,点击Record展开,跳出的结果中包含List列表,再点击List展开,跳出了20行记录。
STEP 4 点击菜单栏转换下的到表,每一行记录都变成了Table表,然后点击列标题右侧的展开按钮,网页上第1页的20行数据就读取进来了。
STEP 5 尝试将获取数据的代码中pageSize(每页行数)改为100,发现返回的结果无变化,改为1000,直接返回空。如果修改pageIndex为2,会发现可以获取网页上第2页的数据,因此,可以利用这个特点,把pageIndex在高级查询编辑器中改为参数,整个查询变成了一个自定义函数。
= (Page) =>
let
Source = let
Headers = [
Referer = "https://fund.eastmoney.com/",
User_Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
],
Source = Web.Contents("https://api.fund.eastmoney.com/f10/lsjz", [
Query = [
fundCode = "004853",
pageIndex = Text.From(Page),
pageSize = "20",
startDate = "",
endDate = ""
],
Headers = Headers
])
in
Source,
#"Imported JSON" = Json.Document(Source,65001),
Data = #"Imported JSON"[Data],
LSJZList = Data[LSJZList],
#"Converted to Table" = Table.FromList(LSJZList, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded {0}" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"FSRQ", "DWJZ", "LJJZ", "SDATE", "ACTUALSYI", "NAVTYPE", "JZZZL", "SGZT", "SHZT", "FHFCZ", "FHFCBZ", "DTYPE", "FHSP"}, {"FSRQ", "DWJZ", "LJJZ", "SDATE", "ACTUALSYI", "NAVTYPE", "JZZZL", "SGZT", "SHZT", "FHFCZ", "FHFCBZ", "DTYPE", "FHSP"})
in
#"Expanded {0}"
STEP 6 具体有多少页每只基金都不一样。从JSN文件中可以获取,TotalCount就是总条数,将JSN文件内容转换到表中,筛选TotalCount把1762这个数据筛选出来,数据类型改为整数。
STEP 7 点击菜单栏添加列下的自定义列,总条数除以20就是页数,有余数的时候需要加1,取出来1到总页数的数字。点击新建列标题右侧的按钮,展开到行,可以得到1到总页数的多行表。
if Number.Mod([Column1],20)=1
then List.Numbers(1,Number.IntegerDivide([Column1],20)+1)
else List.Numbers(1,Number.Round([Column1]/20))
STEP 8 继续添加列,用自定义列作为STEP 5生成的自定义函数查询1的参数,每一行都会把每个页码的多行数据表取出来。
查询1([自定义])
STEP 9 删除其他列,然后点击列标题右侧的展开按钮,留下需要的列,修改列名称、数据类型,加载刷新后就得到了这个基金代码对应的1762条数据。
拓展
如果需要获取多只基金编码的数据,基于多个基金编码获取页码,然后让自定义函数调用基金编码和页码两个参数,就可以一次性获取多只基金的数据了。