影刀RPA RESTful API分页处理的多种方式:偏移量与游标翻页全覆盖

影刀RPA RESTful API分页处理的多种方式:偏移量与游标翻页全覆盖
影刀RPA RESTful API分页处理的多种方式偏移量与游标翻页全覆盖作者林焱调用API接口采集数据翻页是最基本的操作。但不同接口的翻页方式差异很大——有的用offsetlimit、有的用pagepageSize、有的用游标cursor、还有的用Link Header。这篇把常见的分页模式都讲清楚每种给出影刀Python代码块的实现。模式一offset limit 分页最常见接口示例GET /api/data?offset0limit20含义跳过0条数据取20条。下一页是offset20再下一页是offset40。importrequests all_data[]offset0limit50whileTrue:resprequests.get(fhttps://api.example.com/data,params{offset:offset,limit:limit},headers{Authorization:Bearer xxx})dataresp.json()itemsdata[data][items]ifnotitems:# 没有更多数据breakall_data.extend(items)offsetlimitprint(f已采集{len(all_data)}条)print(f共采集{len(all_data)}条)关键点永远用返回的items数量判断是否结束不要用total计数有些接口的total不准。模式二page pageSize 分页店群矩阵自动化突破运营极限接口示例GET /api/data?page1pageSize20all_data[]page1page_size50whileTrue:resprequests.get(fhttps://api.example.com/data,params{page:page,pageSize:page_size},headers{Authorization:Bearer xxx})dataresp.json()itemsdata[data][list]![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b5d0251e49fa4e79b5a073f9d2970086.png#pic_center)ifnotitems:breakall_data.extend(items)totaldata[data][total]# 总条数total_pages(totalpage_size-1)//page_sizeprint(f第{page}/{total_pages}页已采集{len(all_data)}条)page1模式三cursor游标分页接口示例GET /api/data?cursorxxxlimit20返回中包含next_cursor下一页用它请求。没有next_cursor表示结束。all_data[]cursorNonelimit50whileTrue:params{limit:limit}ifcursor:params[cursor]cursor resprequests.get(fhttps://api.example.com/data,paramsparams,headers{Authorization:Bearer xxx})dataresp.json()itemsdata[data][records]all_data.extend(items)cursordata[data].get(next_cursor)ifnotcursor:breakprint(f采集完成共{len(all_data)}条)游标分页的好处即使数据在翻页过程中有新增或删除也不会漏数据或重复。适合实时性要求高的场景。模式四Link Header 分页GitHub API就是这种响应头里带Link字段包含下一页URLLink: https://api.github.com/repos?page2; relnextimportre urlhttps://api.github.com/repos/octocat/hello-world/issuesall_data[]whileurl:resprequests.get(url,headers{Accept:application/vnd.githubjson})all_data.extend(resp.json())![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/280d842b1ca14248a87edd282b92fe2d.png#pic_center)# 解析Link Header找下一页link_headerresp.headers.get(Link,)next_matchre.search(r([^]);\s*relnext,link_header)urlnext_match.group(1)ifnext_matchelseNoneprint(f共采集{len(all_data)}条Issue)模式五scroll滚动分页Elasticsearch风格先发初始请求拿到scroll_id后续用scroll_id翻页# 初始请求resprequests.post(https://es.example.com/index/_search?scroll1m,json{query:{match_all:{}},size:100})dataresp.json()scroll_iddata[_scroll_id]all_datadata[hits][hits]# 循环翻页whileTrue:resprequests.post(https://es.example.com/_search/scroll,json{scroll:1m,scroll_id:scroll_id})dataresp.json()hitsdata[hits][hits]ifnothits:breakall_data.extend(hits)踩坑实录坑1最后一页的items数量小于pageSize很多新手用if len(items) page_size判断结束——这在9成情况下是对的。但有些接口最后一页恰好返回了整页数据total正好是pageSize的整数倍就会多请求一次空页。最稳妥的判断是if not items。temu店群自动化报活动案例坑2total字段不准有些接口的total是所有数据的估计值不是精确值中间数据有增删就会偏差。不要用total计算总页数来控制循环用items是否为空来控制。坑3并发翻页导致数据重复有人试图用多线程加速翻页每个线程负责一页结果因为数据在翻页过程中有变动导致重复或遗漏。分页采集必须串行一页一页来不能并行。坑4请求太快触发限速翻页循环里不加延时一秒几十个请求很容易触发API限速。每个请求之间至少加time.sleep(0.1)限速严格的接口加到0.5甚至1秒。通用翻页函数模板deffetch_all_pages(url,headers,page_parampage,start1,size50):通用的翻页采集函数all_data[]pagestartwhileTrue:params{page_param:page,pageSize:size}resprequests.get(url,paramsparams,headersheaders)dataresp.json()itemsdata[data].get(list,data[data].get(items,[]))ifnotitems:breakall_data.extend(items)page1returnall_data把你的具体URL和headers传进去就行适配大多数API。写在最后翻页看起来简单但不同API的实现方式千差万别。掌握这五种模式99%的API分页场景都能应对。关键不是背代码而是拿到一个接口后能快速识别它是哪种分页模式。