Python-如何通过分页API循环获取数据(Harvest)

时间:2018-10-30 11:29:15

标签: python api loops get harvest


首先,我已经使用Python大约两天了,所以我不一定了解最佳实践或所有术语……。我通过反向工程学得最好,下面的代码基于Harvest的官方文档以及我在google-fu

中发现的其他内容

我的请求是从Harvest中下载所有时间条目记录,并另存为JSON(或者理想情况下为CSV文件)。

Official Python Example from Harvest Git Hub

这是我改编的代码(包括所有输出,在最终代码中不是必需的,但对我的学习很方便):

import requests, json, urllib.request

#Set variables for authorisation
AUTH = "REDACTED"
ACCOUNT = "REDACTED"

URL = "https://api.harvestapp.com/v2/time_entries"
HEADERS = { "Authorization": AUTH,
            "Harvest-Account-ID": ACCOUNT}
PAGENO = str("5")

request = urllib.request.Request(url=URL+"?page="+PAGENO, headers=HEADERS)
response = urllib.request.urlopen(request, timeout=5)
responseBody = response.read().decode("utf-8")
jsonResponse = json.loads(responseBody)

# Find the values for pagination
parsed = json.loads(responseBody)
links_first = parsed["links"]["first"]
links_last = parsed["links"]["last"]
links_next = parsed["links"]["next"]
links_previous = parsed["links"]["previous"]
nextpage = parsed["next_page"]
page = parsed["page"]
perpage = parsed["per_page"]
prevpage = parsed["previous_page"]
totalentries = parsed["total_entries"]
totalpages = parsed["total_pages"]

#Print the output
print(json.dumps(jsonResponse, sort_keys=True, indent=4))
print("first link : " + links_first)
print("last link : " + links_last)
print("next page : " + str(nextpage))
print("page : " + str(page))
print("per page : " + str(perpage))
print("total records : " + str(totalentries))
print("total pages : " + str(totalpages))

输出响应为
“压缩文本(5816行)”
第一个链接:https://api.harvestapp.com/v2/time_entries?page=1&per_page=100
最后一个链接:https://api.harvestapp.com/v2/time_entries?page=379&per_page=100
下一页:6
页:5
每页:100
总记录:37874
总页数:379

请问有人能建议最好的方法来循环浏览页面以形成一个JSON文件吗? 如果您还能够建议最好的方法,然后输出该JSON文件,我将不胜感激。

2 个答案:

答案 0 :(得分:2)

我一直在使用以下代码检索所有时间条目。也许它可能更有效,但是它可以工作。函数get_all_time_entries循环浏览所有页面,并将JSON格式的响应附加到all_time_entries数组中,最后返回该数组。

import requests
import json

def get_all_time_entries():

    url_address = "https://api.harvestapp.com/v2/time_entries"  
    headers = {
        "Authorization": "Bearer " + "xxxxxxxxxx",
        "Harvest-Account-ID": "xxxxxx"
    }

    # find out total number of pages
    r = requests.get(url=url_address, headers=headers).json()
    total_pages = int(r['total_pages'])

    # results will be appended to this list
    all_time_entries = []

    # loop through all pages and return JSON object
    for page in range(1, total_pages):

        url = "https://api.harvestapp.com/v2/time_entries?page="+str(page)              
        response = requests.get(url=url, headers=headers).json()        
        all_time_entries.append(response)       
        page += 1

    # prettify JSON
    data = json.dumps(all_time_entries, sort_keys=True, indent=4)

    return data

print(get_all_time_entries())

您 在powershell等中运行时,可以轻松地将带有“>”的脚本输出定向到本地文件夹。

例如:

Python.exe example.py> C:\ temp \ all_time_entries.json

希望这会有所帮助!

答案 1 :(得分:0)

有一个支持Harvest API v2的Python库。

该库支持所有身份验证方法,请求速率限制,响应代码,并具有每个响应对象的数据类。

该库已经过很好的测试,因此您将在测试中获得每个端点的用法示例。测试使用了正式的Harvest示例。

此外,还有一个示例详细的时间报告,该报告继承了Harvest对象。详细时间报告的测试显示了如何使用它。

库是从Harvest软件目录中引用的; https://www.getharvest.com/integrations/python-library

项目网址; https://github.com/bradbase/python-harvest_apiv2

我拥有这个项目。


from harvest import Harvest
from .harvestdataclasses import *

class MyTimeEntries(Harvest):

    def __init__(self, uri, auth):
        super().__init__(uri, auth)


    def time_entries(self):
        time_entry_results = []
       
        time_entries = self.time_entries()
        time_entry_results.extend(time_entries.time_entries)
        if time_entries.total_pages > 1:
            for page in range(2, time_entries.total_pages + 1):
                time_entries = self.time_entries(page=page)
                time_entry_results.extend(time_entries.time_entries)
        
        return time_entry_results

personal_access_token = PersonalAccessToken('ACCOUNT_NUMBER', 'PERSONAL_ACCESS_TOKEN')
my_report = MyTimeEntries('https://api.harvestapp.com/api/v2', personal_access_token)
time_entries = my_report.time_entries()