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

如何在数据「追平」时停止API分页迭代请求?

分页API增量同步:重复记录块检测实现

场景说明

测试用免费分页API端点:https://api.instantwebtools.net/v1/passenger?page=0&size=10,该场景与实际需求高度契合:

  • 通过迭代替换URL中的page=0为page=i获取多页数据
  • 单页响应包含固定10条记录(实际场景为48-52条随机变动)
  • 无主键或索引,需通过行值比对判断重复

核心需求

每次运行代码时:

  • 优先获取最新数据,将新增记录添加到已保存表的顶部
  • 当请求返回的整页记录块已存在于已保存表中时,立即停止后续API请求迭代

伪工作流

  • 首次运行:检索并存储所有记录
  • 再次运行:
    • 获取当前页响应记录
    • 对比响应记录与已保存表:
      • 若记录块未存在:添加到数据集顶部,继续迭代下一页
      • 若记录块已存在:终止迭代

优化方案(避免双重循环)

为提升效率,采用整记录块比对而非单条行检查:

  • 动态获取当前响应的记录数量(适配实际场景的48-52条随机变动)
  • 以该记录数为步长,检查已保存表的开头部分是否存在完全匹配的记录块(如响应有9条记录,则比对表中j:j+8行与响应行)
  • 仅当整块匹配时才停止迭代,避免因单条历史追溯记录导致的提前终止

带重复检测的完整Power Query M代码

let
    // 加载已保存的历史数据(替换为你的实际已保存查询/数据源)
    SavedData = try SavedPassengerData otherwise Table.FromRecords({}),
    SavedRowCount = Table.RowCount(SavedData),

    // 定义API相关变量
    _base_url = "https://api.instantwebtools.net/v1/passenger?page=",
    _end_url = "&size=10",
    _max_iterations = 1000, // 实际场景可设为更大值,防止无限循环

    // 定义单页数据获取函数
    FnGetOnePage = (page_num as number) as list =>
            let
                // API限流延迟
                sleep = Function.InvokeAfter(() => null, #duration(0,0,0,1)),
                url = _base_url & Number.ToText(page_num) & _end_url,
                Source = Json.Document(Web.Contents(url)),
                // 提取并标准化数据结构(与SavedData结构对齐)
                RawData = Source[data],
                ExpandedAirline = List.Transform(RawData, (row) => 
                    Record.Combine({
                        Record.RemoveFields(row, {"airline"}),
                        Record.RenameFields(row[airline]{0}, {"id", "name", "country", "logo", "slogan", "head_quaters", "website", "established"}, 
                                            {"data.airline.id", "data.airline.name", "data.airline.country", "data.airline.logo", "data.airline.slogan", "data.airline.head_quaters", "data.airline.website", "data.airline.established"})
                    })
                ),
                StandardizedData = Table.FromRecords(ExpandedAirline)
            in
                StandardizedData,

    // 迭代获取数据,加入重复块检测
    GeneratedList = List.Generate(
        () => [
            page = 0,
            current_data = FnGetOnePage(0),
            is_duplicate = if SavedRowCount >= Table.RowCount(current_data) then 
                Table.Equals(Table.FirstN(SavedData, Table.RowCount(current_data)), current_data) 
            else false
        ],
        // 终止条件:未达最大迭代次数、当前数据不为空、且未检测到重复块
        each [page] < _max_iterations and Table.RowCount([current_data]) > 0 and not [is_duplicate],
        each [
            page = [page] + 1,
            current_data = FnGetOnePage([page]),
            is_duplicate = if SavedRowCount >= Table.RowCount(current_data) then 
                Table.Equals(Table.FirstN(SavedData, Table.RowCount(current_data)), current_data) 
            else false
        ],
        each [current_data]
    ),

    // 合并新增数据与历史数据
    CombinedData = if List.IsEmpty(GeneratedList) then 
        SavedData 
    else 
        Table.Combine(GeneratedList) & SavedData,

    // 统一数据类型(与原代码对齐)
    #"Changed Type" = Table.TransformColumnTypes(CombinedData,{
        {"_id", type text}, {"name", type text}, {"trips", Int64.Type}, {"__v", Int64.Type},
        {"data.airline.id", Int64.Type}, {"data.airline.name", type text}, {"data.airline.country", type text},
        {"data.airline.logo", type text}, {"data.airline.slogan", type text}, {"data.airline.head_quaters", type text},
        {"data.airline.website", type text}, {"data.airline.established", Int64.Type}
    })
in
    #"Changed Type"

代码说明

  1. 历史数据加载:通过SavedPassengerData加载已保存的历史表,首次运行时为空表
  2. 单页数据标准化:将API返回的嵌套结构展开,确保与历史表结构完全对齐,保证比对准确性
  3. 重复块检测:在List.Generate中,每次获取新页后,检查历史表的前N行(N为当前页记录数)是否与当前页完全匹配,匹配则终止迭代
  4. 数据合并:将新增的多页数据合并后追加到历史表顶部,实现最新数据优先

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:25:27