在Python中使用next_link进行分页的正确方法是什么?

如何解决在Python中使用next_link进行分页的正确方法是什么?

我正在尝试为每个“切片”收集250条记录。我总共有1429条记录,所以6片250条记录足以收集我的所有记录。我尝试使用下面的代码执行此操作,但是在运行它时,它只返回251至500条记录。我的预期结果是收到1至1429条记录。有人可以告诉我我做错了吗?

   import requests
   import json
   import math
       
    res = r.json()
    token = res['access_token']
    headers = {'Authorization': 'Bearer ' + token}
    proxies = {'https': 'proxy.***.***.com:8080'}
    mod_date =  'ModifiedOn gt 2020-01-31'
    col = 'Field1,Field2,Field3,Field4'
    
    params1 = (('$count','true'),)       
    response1 = requests.get('https://***-***-***.***.nl/odata/***',headers=headers,params=params1,proxies=proxies)
   
    data = response1.json()
            
    next_link = data['@odata.nextLink'] #<--- this is my 'next_link' link.
    total_records = data['@odata.count'] #<--- this are the total records '1429'
    records_per_page = next_link[313:] #<--- this are the records per page '250'
    
    total_pages = total_records / int(records_per_page)  #<--- these are the total pages '5.7'
    
    list_to_store_all_sclices = []
    list_pages = [i for i in range(1,math.ceil(total_pages) +1)] #<--- '5,7' is rounded to 6 and placed in list.
   
    
    for x in list_pages:
        response2 = requests.get(next_link.format(x),proxies=proxies)
        data = response2.json()
        list_to_store_all_sclices.append(data)
        print(list_to_store_all_sclices)

解决方法

您似乎在这里犯了两个错误:

  1. 您创建了一个列表,其中填充了list_to_store_all_sclices = [] 但是您没有append到该列表的第一个结果。

仅在发出第二个请求后附加数据。

  1. 您从第一个结果中获得了下一个链接。但是随后您尝试在其上使用format。当您尝试格式化没有方括号的字符串时,不会发生任何事情。自己尝试一下:
link = 'this is a string'
link2 = 'this is {}'
insert = 'some insertion'
print(link.format(insert))
print(link2.format(insert))

查看formatting synthax上的文档,以了解格式化的工作原理。

由于您没有提供next_link的更多示例,并且服务器响应实际上是什么样的,因此我们无法为您提供确切的说明。但是我们可以假设服务器为每个响应提供了一个新的链接。因此,您需要在获得每个响应后捕获它,并在您的请求中使用它。否则,您将一遍又一遍地使用相同的链接,就像您提供的代码一样。

您的代码可能看起来像这样:

while next_link:
    new_response = requests.get(next_link,headers=headers,proxies=proxies)
    new_data = new_response.json()
    list_to_store_all_sclices.append(new_data)
    print(list_to_store_all_sclices)
    next_link = new_data.get('@odata.nextLink',None)

但是您需要查看next_link的外观,以便知道是否/如何修改它以发出正确的请求。交互式外壳程序是一个很好的工具。

编辑以回答您的问题:

  1. 现在我们只在谈论1429条记录,如果我有数百万个记录,那python处理的内容就不那么多了吗?

这实际上取决于记录的大小。例如,如果每个字符串都是10个字符的字符串,那么在内存中存储很多字符串就不会有问题。如果它们很大,则需要开始考虑一种将数据存储到内存之外的方法(存储在文件或数据库中)。

  1. 最后两行代码在做什么?(不是印刷品)

由于您拥有next_link = data['@odata.nextLink'],因此我认为数据是字典。字典有一个get method。它返回提供的键的值。

如果字典中没有这样的键,则默认情况下,它返回None,与使用方括号表示法获取键的值形成对比,如果键不在字典中,则返回KeyError

如果请求的键不在词典中,您还可以指定要返回的值。在示例中,我已明确使用None,但您不必这样做。

  1. 您的None在做什么?

只要表达式为真,while语句就会重复执行代码块。

FalseNone,空字符串,空字典等都是“虚假的”,这意味着服务器不提供next_link而我们的{{1} }变量为next_link,循环中断。

您可以阅读有关真值测试in the docs的更多信息。

使用您的代码,我收到251条记录,直到1429年。我错过了 前250条记录。

正如我在1.中所说,在您的代码中,您没有将第一个响应中的数据附加到None

因此,您需要创建列表,将第一个响应数据附加到该列表,然后继续下一个请求。它应该看起来像这样:

list_to_store_all_sclices

您还需要考虑的是,使用代码创建字典列表。您可能需要考虑结果数据的结构,以及它如何影响您将来的需求和结果的使用。

,

如果一次只能获取250个项目,并且仅使用下一页一次,那么您将只能获取接下来的250个元素,因此只能获取500个元素。通常不知道您可以先获得多少个元素,我最近用这种结构解决了这个问题

    json_dict,links = self._retrieve_transactions_json()
    output_list = parse_json_list(json_dict) # this is my function dont
    while links['next'] and ctr < num_transactions: # if there is a next link keep going,get all accounts
         json_dict,links = self._retrieve_transactions_json(links['next']) # ditto my class 
         output_list.extend(parse_json_list(json_dict)) # ditto above

在不断获得下一笔交易之前,我一直在这里进行下一步工作。希望此代码模式有所帮助。这里的要点是,每次获取data时,您都将需要遍历data['next'] #next page直到其为null或根据API规范返回的最后一页

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-