无法通过 Python 的分页 API 响应循环
Unable to loop through paged API responses with Python
所以,我正在为这个问题挠头。使用 HubSpot 的 API,我需要获取我客户 "portal"(帐户)中所有公司的列表。遗憾的是,标准 API 一次只能呼叫 return 100 家公司。当它 return 响应时,它包含两个参数,可以通过响应进行分页。
其中一个是 "has-more": True
(这让您知道是否可以期待更多页面),另一个是 "offset":12345678
(用于抵消请求的时间戳。)
这两个参数可以传递回下一个 API 调用以获取下一页。因此,例如,初始 API 调用可能如下所示:
"https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}".format(hapikey=wta_hubspot_api_key)
而跟进电话可能如下所示:
"https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}&offset={offset}".format(hapikey=wta_hubspot_api_key, offset=offset)
这就是我到目前为止尝试过的方法:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import os.path
import requests
import json
import csv
import glob2
import shutil
import time
import time as howLong
from time import sleep
from time import gmtime, strftime
HubSpot_Customer_Portal_ID = "XXXXXX"
wta_hubspot_api_key = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
findCSV = glob2.glob('*contact*.csv')
theDate = time=strftime("%Y-%m-%d", gmtime())
theTime = time=strftime("%H:%M:%S", gmtime())
try:
testData = findCSV[0]
except IndexError:
print ("\nSyncronisation attempted on {date} at {time}: There are no \"contact\" CSVs, please upload one and try again.\n").format(date=theDate, time=theTime)
print("====================================================================================================================\n")
sys.exit()
for theCSV in findCSV:
def get_companies():
create_get_recent_companies_call = "https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}".format(hapikey=wta_hubspot_api_key)
headers = {'content-type': 'application/json'}
create_get_recent_companies_response = requests.get(create_get_recent_companies_call, headers=headers)
if create_get_recent_companies_response.status_code == 200:
offset = create_get_recent_companies_response.json()[u'offset']
hasMore = create_get_recent_companies_response.json()[u'has-more']
while hasMore == True:
for i in create_get_recent_companies_response.json()[u'companies']:
get_more_companies_call = "https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}&offset={offset}".format(hapikey=wta_hubspot_api_key, offset=offset)
get_more_companies_call_response = requests.get(get_more_companies_call, headers=headers)
companyName = i[u'properties'][u'name'][u'value']
print("{companyName}".format(companyName=companyName))
else:
print("Something went wrong, check the supplied field values.\n")
print(json.dumps(create_get_recent_companies_response.json(), sort_keys=True, indent=4))
if __name__ == "__main__":
get_companies()
sys.exit()
问题是它只是保持 return 相同的初始 100 个结果;发生这种情况是因为参数 "has-more":True
在初始调用时为真,因此它只会保持 returning 相同的参数...
我的理想情况是我能够跨大约 120 个响应页面解析所有公司(大约有 12000 家公司)。当我浏览每一页时,我想将它的 JSON 内容附加到一个列表中,这样最终我就有了这个列表,其中包含所有 120 页的 JSON 响应,这样我就可以解析该列表用于不同的功能。
我迫切需要一个解决方案:(
这是我在主脚本中替换的函数:
def get_companies():
create_get_recent_companies_call = "https://api.hubapi.com/companies/v2/companies/recent/modified?hapikey={hapikey}".format(hapikey=wta_hubspot_api_key)
headers = {'content-type': 'application/json'}
create_get_recent_companies_response = requests.get(create_get_recent_companies_call, headers=headers)
if create_get_recent_companies_response.status_code == 200:
for i in create_get_recent_companies_response.json()[u'results']:
company_name = i[u'properties'][u'name'][u'value']
#print(company_name)
if row[0].lower() == str(company_name).lower():
contact_company_id = i[u'companyId']
#print(contact_company_id)
return contact_company_id
else:
print("Something went wrong, check the supplied field values.\n")
#print(json.dumps(create_get_recent_companies_response.json(), sort_keys=True, indent=4))
问题似乎是:
- 您在第一次调用时获得了偏移量,但不对此次调用 returns 的实际公司数据执行任何操作。
- 然后您在 while 循环中使用相同的偏移量;您永远不会使用后续电话中的新电话。这就是为什么你每次都得到相同的公司。
我认为 get_companies()
的代码应该适合您。显然,我无法测试它,但希望它没问题:
def get_companies():
create_get_recent_companies_call = "https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}".format(hapikey=wta_hubspot_api_key)
headers = {'content-type': 'application/json'}
create_get_recent_companies_response = requests.get(create_get_recent_companies_call, headers=headers)
if create_get_recent_companies_response.status_code == 200:
while True:
for i in create_get_recent_companies_response.json()[u'companies']:
companyName = i[u'properties'][u'name'][u'value']
print("{companyName}".format(companyName=companyName))
offset = create_get_recent_companies_response.json()[u'offset']
hasMore = create_get_recent_companies_response.json()[u'has-more']
if not hasMore:
break
else:
create_get_recent_companies_call = "https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}&offset={offset}".format(hapikey=wta_hubspot_api_key, offset=offset)
create_get_recent_companies_response = requests.get(create_get_recent_companies_call, headers=headers)
else:
print("Something went wrong, check the supplied field values.\n")
print(json.dumps(create_get_recent_companies_response.json(), sort_keys=True, indent=4))
严格来说,break
之后的 else
不是必需的,但它与 Zen of Python "Explicit is better than implicit"
保持一致
请注意,您只检查一次 200 响应代码,如果循环中出现问题,您将错过它。您可能应该将所有调用都放在循环中,并每次都检查是否有正确的响应。
所以,我正在为这个问题挠头。使用 HubSpot 的 API,我需要获取我客户 "portal"(帐户)中所有公司的列表。遗憾的是,标准 API 一次只能呼叫 return 100 家公司。当它 return 响应时,它包含两个参数,可以通过响应进行分页。
其中一个是 "has-more": True
(这让您知道是否可以期待更多页面),另一个是 "offset":12345678
(用于抵消请求的时间戳。)
这两个参数可以传递回下一个 API 调用以获取下一页。因此,例如,初始 API 调用可能如下所示:
"https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}".format(hapikey=wta_hubspot_api_key)
而跟进电话可能如下所示:
"https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}&offset={offset}".format(hapikey=wta_hubspot_api_key, offset=offset)
这就是我到目前为止尝试过的方法:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import os.path
import requests
import json
import csv
import glob2
import shutil
import time
import time as howLong
from time import sleep
from time import gmtime, strftime
HubSpot_Customer_Portal_ID = "XXXXXX"
wta_hubspot_api_key = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
findCSV = glob2.glob('*contact*.csv')
theDate = time=strftime("%Y-%m-%d", gmtime())
theTime = time=strftime("%H:%M:%S", gmtime())
try:
testData = findCSV[0]
except IndexError:
print ("\nSyncronisation attempted on {date} at {time}: There are no \"contact\" CSVs, please upload one and try again.\n").format(date=theDate, time=theTime)
print("====================================================================================================================\n")
sys.exit()
for theCSV in findCSV:
def get_companies():
create_get_recent_companies_call = "https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}".format(hapikey=wta_hubspot_api_key)
headers = {'content-type': 'application/json'}
create_get_recent_companies_response = requests.get(create_get_recent_companies_call, headers=headers)
if create_get_recent_companies_response.status_code == 200:
offset = create_get_recent_companies_response.json()[u'offset']
hasMore = create_get_recent_companies_response.json()[u'has-more']
while hasMore == True:
for i in create_get_recent_companies_response.json()[u'companies']:
get_more_companies_call = "https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}&offset={offset}".format(hapikey=wta_hubspot_api_key, offset=offset)
get_more_companies_call_response = requests.get(get_more_companies_call, headers=headers)
companyName = i[u'properties'][u'name'][u'value']
print("{companyName}".format(companyName=companyName))
else:
print("Something went wrong, check the supplied field values.\n")
print(json.dumps(create_get_recent_companies_response.json(), sort_keys=True, indent=4))
if __name__ == "__main__":
get_companies()
sys.exit()
问题是它只是保持 return 相同的初始 100 个结果;发生这种情况是因为参数 "has-more":True
在初始调用时为真,因此它只会保持 returning 相同的参数...
我的理想情况是我能够跨大约 120 个响应页面解析所有公司(大约有 12000 家公司)。当我浏览每一页时,我想将它的 JSON 内容附加到一个列表中,这样最终我就有了这个列表,其中包含所有 120 页的 JSON 响应,这样我就可以解析该列表用于不同的功能。
我迫切需要一个解决方案:(
这是我在主脚本中替换的函数:
def get_companies():
create_get_recent_companies_call = "https://api.hubapi.com/companies/v2/companies/recent/modified?hapikey={hapikey}".format(hapikey=wta_hubspot_api_key)
headers = {'content-type': 'application/json'}
create_get_recent_companies_response = requests.get(create_get_recent_companies_call, headers=headers)
if create_get_recent_companies_response.status_code == 200:
for i in create_get_recent_companies_response.json()[u'results']:
company_name = i[u'properties'][u'name'][u'value']
#print(company_name)
if row[0].lower() == str(company_name).lower():
contact_company_id = i[u'companyId']
#print(contact_company_id)
return contact_company_id
else:
print("Something went wrong, check the supplied field values.\n")
#print(json.dumps(create_get_recent_companies_response.json(), sort_keys=True, indent=4))
问题似乎是:
- 您在第一次调用时获得了偏移量,但不对此次调用 returns 的实际公司数据执行任何操作。
- 然后您在 while 循环中使用相同的偏移量;您永远不会使用后续电话中的新电话。这就是为什么你每次都得到相同的公司。
我认为 get_companies()
的代码应该适合您。显然,我无法测试它,但希望它没问题:
def get_companies():
create_get_recent_companies_call = "https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}".format(hapikey=wta_hubspot_api_key)
headers = {'content-type': 'application/json'}
create_get_recent_companies_response = requests.get(create_get_recent_companies_call, headers=headers)
if create_get_recent_companies_response.status_code == 200:
while True:
for i in create_get_recent_companies_response.json()[u'companies']:
companyName = i[u'properties'][u'name'][u'value']
print("{companyName}".format(companyName=companyName))
offset = create_get_recent_companies_response.json()[u'offset']
hasMore = create_get_recent_companies_response.json()[u'has-more']
if not hasMore:
break
else:
create_get_recent_companies_call = "https://api.hubapi.com/companies/v2/companies/?hapikey={hapikey}&offset={offset}".format(hapikey=wta_hubspot_api_key, offset=offset)
create_get_recent_companies_response = requests.get(create_get_recent_companies_call, headers=headers)
else:
print("Something went wrong, check the supplied field values.\n")
print(json.dumps(create_get_recent_companies_response.json(), sort_keys=True, indent=4))
严格来说,break
之后的 else
不是必需的,但它与 Zen of Python "Explicit is better than implicit"
请注意,您只检查一次 200 响应代码,如果循环中出现问题,您将错过它。您可能应该将所有调用都放在循环中,并每次都检查是否有正确的响应。