You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Power Query带参数分页获取API全页数据报错求助

问题描述

使用Power BI Desktop的Power Query Editor获取AppFollow API的所有分页响应时,调用自定义函数出现错误:Expression.Error: The parameter is expected to be of type Text.Type or Binary.Type。需求是高效获取所有页面(总页数在响应的reviews.page.total字段),且需考虑API信用计费的成本。

当前自定义函数代码:

(ext_id as text, from as text, to as text) =>
let
    BaseURL     = "https://api.appfollow.io/api/v2/reviews?",
    token       = "[redacted]",
    Query       = "ext_id=" & ext_id & "&from=" & from & "&to=" & to,

    GetJson = (Url) =>
        let 
            Options     = [Headers=[Accept="application/json", #"X-AppFollow-API-Token"= token ]],
            RawData     = Web.Contents(Url, Options),
            Json        = Json.Document(RawData)
        in  Json,

    GetPageCount = () =>
        let Url             = BaseURL & Query,
            response        = GetJson(Url),
            toJson          = Json.Document(response),
            total           = toJson[reviews]{0}[page][total]
        in  total,

    GetPage = (Index) =>
        let
            Page    = "&page=" & (Index),
            Url     = BaseURL & Query & Page,
            Json    = GetJson(Url),
            Value   = Json[reviews]
        in  Value,

    PageCount       = GetPageCount(),
    PageIndicies     = {0..PageCount -1},
    Pages           = List.Transform(PageIndicies, each GetPage(_)),
    Results         = List.Union(Pages),

#"Converted to Table" = Table.FromRecords(Results)

in
#"Converted to Table"

API示例响应:

{
    "query": "/api/reviews?cid=[cid-here]&ext_id=[ext-id-here&from=2023-01-01&to=2023-01-31&host=global4.appfollow.io&method=GET&real_ip=xxx.xxx.xxx.xx",
    "reviews": {
        "list": [
            {
                "data": "[removed data]"
            }
        ],
        "total": 286,
        "page": {
            "current": 1,
            "total": 3,
            "next": 2,
            "prev": null
        },
        "ext_id": "ext-id-here",
        "store": "as"
    }
}

错误详情:

Expression.Error: The parameter is expected to be of type Text.Type or Binary.Type.
Details:
    query=/api/reviews?ext_id=[ext-id-here]&to=2023-01-31&from=2023-01-01&dev103=1&cid=[cid-here]&host=global4.appfollow.io&method=GET&real_ip=xxx.xx.xxx.xxx
    reviews=[Record]
错误原因分析
  • 重复解析JSON:GetJson函数已经返回Json.Document(RawData)解析后的Record对象,但GetPageCount里又调用Json.Document(response),将已解析的Record作为参数传入,而Json.Document仅接受文本或二进制类型,这是报错的直接原因。
  • 响应路径错误:示例响应中reviews是Record而非List,代码中toJson[reviews]{0}[page][total]用{0}索引List是错误的,应直接访问reviews[page][total]。
  • 页码逻辑错误:API返回的page.current是1-based(第一页为1),但代码生成的页码是{0..PageCount-1},会触发page=0的无效请求,同时遗漏最后一页。
  • 数据提取错误:GetPage函数返回整个reviewsRecord而非评论列表reviews[list],导致List.Union无法处理非List类型的数据。
修复后的代码
(ext_id as text, from as text, to as text) =>
let
    BaseURL     = "https://api.appfollow.io/api/v2/reviews?",
    token       = "[redacted]",
    Query       = "ext_id=" & ext_id & "&from=" & from & "&to=" & to,

    GetJson = (Url) =>
        let 
            Options     = [Headers=[Accept="application/json", #"X-AppFollow-API-Token"= token ]],
            RawData     = Web.Contents(Url, Options),
            Json        = Json.Document(RawData)
        in  Json,

    // 获取第一页数据并缓存,避免重复调用API浪费信用
    FirstPageUrl = BaseURL & Query,
    FirstPageData = GetJson(FirstPageUrl),
    PageCount = FirstPageData[reviews][page][total],
    
    // 生成1到总页数的页码列表
    PageIndices = {1..PageCount},
    
    // 获取指定页码的评论列表
    GetPage = (Index) =>
        let
            // 第一页直接用缓存数据,无需重复调用
            PageData = if Index = 1 then FirstPageData else GetJson(BaseURL & Query & "&page=" & Text.From(Index)),
            ReviewList = PageData[reviews][list]
        in  ReviewList,

    // 获取所有页面的评论列表
    AllPages = List.Transform(PageIndices, each GetPage(_)),
    // 合并所有列表为单列表
    CombinedReviews = List.Combine(AllPages),
    
    // 转换为表格
    #"Converted to Table" = Table.FromRecords(CombinedReviews)
in
#"Converted to Table"
优化说明
  • 缓存第一页数据:首次调用获取第一页时同时拿到总页数,后续直接复用第一页数据,避免重复调用API消耗额外信用。
  • 修正页码逻辑:使用1-based页码匹配API参数要求,确保请求有效。
  • 正确提取评论列表:直接获取reviews[list]作为返回值,保证List.Combine能正常合并所有页面的数据。
  • 显式转换页码为文本:用Text.From(Index)确保页码参数是文本类型,避免类型拼接错误。

内容的提问来源于stack exchange,提问作者MrSalta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 20:01:33