次のスクリプトを作成して、意図したとおりに動作するAPIエンドポイントから画像をダウンロードしました。それは、すべての要求がお互いに待たなければならないので、むしろ遅いということです。フェッチしたいアイテムごとに同期させることができるようにする正しい方法はありますが、個々のアイテムごとにパラレルにすることは可能です。オンラインサービスからこの servicem8 呼ばそれでは、私が達成したいと考えてすることは次のとおりです。PythonリクエストURLが並行して
- 可能なすべての仕事を取得し、IDS =>名前を保つ/およびその他の情報
- 顧客の名前
- は、各添付ファイルをフェッチフェッチ
この3つの手順は、ジョブごとに実行する必要があります。だから私は、お互いに待つ必要がないので、仕事ごとに物事を並行させることができました。
更新:私は理解していない
問題はあなたがたとえば、私はそうするために並行して物事を行うことができ、その唯一のアイテムごとのように1回の呼び出しで項目ごとに3つのコールをバンドルしていることを確認することができます方法ですたとえば、私はアイテムをフェッチ
- したいとき(フェッチ名=>フェッチ説明=>フェッチID)
はそうその私は、並列にしたい項目をフェッチ?
私が働くのではなくスローされている現在のコード:
import requests
import dateutil.parser
import shutil
import os
user = "[email protected]"
passw = "test"
print("Read json")
url = "https://api.servicem8.com/api_1.0/job.json"
r = requests.get(url, auth=(user, passw))
print("finished reading jobs.json file")
scheduled_jobs = []
if r.status_code == 200:
for item in r.json():
scheduled_date = item['job_is_scheduled_until_stamp']
try:
parsed_date = dateutil.parser.parse(scheduled_date)
if parsed_date.year == 2016:
if parsed_date.month == 10:
if parsed_date.day == 10:
url_customer = "https://api.servicem8.com/api_1.0/Company/{}.json".format(item[
'company_uuid'])
c = requests.get(url_customer, auth=(user, passw))
cus_name = c.json()['name']
scheduled_jobs.append(
[item['uuid'], item['generated_job_id'], cus_name])
except ValueError:
pass
for job in scheduled_jobs:
print("fetch for job {}".format(job))
url = "https://api.servicem8.com/api_1.0/Attachment.json?%24filter=related_object_uuid%20eq%20{}".format(job[
0])
r = requests.get(url, auth=(user, passw))
if r.json() == []:
pass
for attachment in r.json():
if attachment['active'] == 1 and attachment['file_type'] != '.pdf':
print("fetch for attachment {}".format(attachment))
url_staff = "https://api.servicem8.com/api_1.0/Staff.json?%24filter=uuid%20eq%20{}".format(
attachment['created_by_staff_uuid'])
s = requests.get(url_staff, auth=(user, passw))
for staff in s.json():
tech = "{}_{}".format(staff['first'], staff['last'])
url = "https://api.servicem8.com/api_1.0/Attachment/{}.file".format(attachment[
'uuid'])
r = requests.get(url, auth=(user, passw), stream=True)
if r.status_code == 200:
creation_date = dateutil.parser.parse(
attachment['timestamp']).strftime("%d.%m.%y")
if not os.path.exists(os.getcwd() + "/{}/{}".format(job[2], job[1])):
os.makedirs(os.getcwd() + "/{}/{}".format(job[2], job[1]))
path = os.getcwd() + "/{}/{}/SC -O {} {}{}".format(
job[2], job[1], creation_date, tech.upper(), attachment['file_type'])
print("writing file to path {}".format(path))
with open(path, 'wb') as f:
r.raw.decode_content = True
shutil.copyfileobj(r.raw, f)
else:
print(r.text)
を更新[14/10] 私は与えられたいくつかのヒントを次のようにコードを更新しました。それに感謝します。最適化できるのは、添付ファイルのダウンロードだけですが、今は問題なく動作しています。私が学んだ面白いことは、あなたがWindowsマシン上にCONフォルダを作成できないということです:-)それを知らなかったのです。
私はdictsの私のリストのいくつかのループを避けようとしていますが、私がすでに演奏しているかどうかはわかりません。 Longestは実際には完全なjsonファイルを読み込んでいます。私は完全にAPIの方法を見つけることができなかったので、それらを完全に読んで、2016年9月のジョブだけを返してください。apiクエリ関数はeq/lt/htで動作するようです。
import requests
import dateutil.parser
import shutil
import os
import pandas as pd
user = ""
passw = ""
FOLDER = os.getcwd()
headers = {"Accept-Encoding": "gzip, deflate"}
import grequests
urls = [
'https://api.servicem8.com/api_1.0/job.json',
'https://api.servicem8.com/api_1.0/Attachment.json',
'https://api.servicem8.com/api_1.0/Staff.json',
'https://api.servicem8.com/api_1.0/Company.json'
]
#Create a set of unsent Requests:
print("Read json files")
rs = (grequests.get(u, auth=(user, passw), headers=headers) for u in urls)
#Send them all at the same time:
jobs,attachments,staffs,companies = grequests.map(rs)
#create dataframes
df_jobs = pd.DataFrame(jobs.json())
df_attachments = pd.DataFrame(attachments.json())
df_staffs = pd.DataFrame(staffs.json())
df_companies = pd.DataFrame(companies.json())
#url_customer = "https://api.servicem8.com/api_1.0/Company/{}.json".format(item['company_uuid'])
#c = requests.get(url_customer, auth=(user, passw))
#url = "https://api.servicem8.com/api_1.0/job.json"
#jobs = requests.get(url, auth=(user, passw), headers=headers)
#print("Reading attachments json")
#url = "https://api.servicem8.com/api_1.0/Attachment.json"
#attachments = requests.get(url, auth=(user, passw), headers=headers)
#print("Reading staff.json")
#url_staff = "https://api.servicem8.com/api_1.0/Staff.json"
#staffs = requests.get(url_staff, auth=(user, passw))
scheduled_jobs = []
if jobs.status_code == 200:
print("finished reading json file")
for job in jobs.json():
scheduled_date = job['job_is_scheduled_until_stamp']
try:
parsed_date = dateutil.parser.parse(scheduled_date)
if parsed_date.year == 2016:
if parsed_date.month == 9:
cus_name = df_companies[df_companies.uuid == job['company_uuid']].iloc[0]['name'].upper()
cus_name = cus_name.replace('/', '')
scheduled_jobs.append([job['uuid'], job['generated_job_id'], cus_name])
except ValueError:
pass
print("{} jobs to fetch".format(len(scheduled_jobs)))
for job in scheduled_jobs:
print("fetch for job attachments {}".format(job))
#url = "https://api.servicem8.com/api_1.0/Attachment.json?%24filter=related_object_uuid%20eq%20{}".format(job[0])
if attachments == []:
pass
for attachment in attachments.json():
if attachment['related_object_uuid'] == job[0]:
if attachment['active'] == 1 and attachment['file_type'] != '.pdf' and attachment['attachment_source'] != 'INVOICE_SIGNOFF':
for staff in staffs.json():
if staff['uuid'] == attachment['created_by_staff_uuid']:
tech = "{}_{}".format(
staff['first'].split()[-1].strip(), staff['last'])
creation_timestamp = dateutil.parser.parse(
attachment['timestamp'])
creation_date = creation_timestamp.strftime("%d.%m.%y")
creation_time = creation_timestamp.strftime("%H_%M_%S")
path = FOLDER + "/{}/{}/SC_-O_D{}_T{}_{}{}".format(
job[2], job[1], creation_date, creation_time, tech.upper(), attachment['file_type'])
# fetch attachment
if not os.path.isfile(path):
url = "https://api.servicem8.com/api_1.0/Attachment/{}.file".format(attachment[
'uuid'])
r = requests.get(url, auth=(user, passw), stream = True)
if r.status_code == 200:
if not os.path.exists(FOLDER + "/{}/{}".format(job[2], job[1])):
os.makedirs(
FOLDER + "/{}/{}".format(job[2], job[1]))
print("writing file to path {}".format(path))
with open(path, 'wb') as f:
r.raw.decode_content = True
shutil.copyfileobj(r.raw, f)
else:
print("file already exists")
else:
print(r.text)
方法の選択に注意してください。これを行うには、ServiceM8 APIのレートが制限されており、同時リクエスト数が多すぎると「HTTP/1.1 429リクエストが多すぎます」 ただし、添付ファイルのリンクを徐々に解決することはできますが、あなたが行く;それらからURLファイルを作成します。ファイルから複数の方法を使って同時にダウンロードすることができます。 'r = requests.get(url、auth =(user、passw)、stream = True)' 'r.url'レスポンスに直接" https:// data-cdn "が含まれています。 servicem8.com/.... "のリンクは、レート制限されません。 – hmedia1
これの効率を大幅に改善する2つの他の簡単な手順: ** 1 **すべてのJob UuidのAttachment APIを呼び出す代わりに、Attachmentsファイル全体を単一の要求で取得し、related_object_uuidあなたが1つのヒットで得た仕事用のuuidsを持っている ** **添付ファイルを正常にダウンロードしたら、ファイルまたはデータベースのどこかに添付ファイルuuidを保存して、uuidがすでに処理されているものはスキップしてください。あなたが添付ファイルダウンローダを実行するたびに、新しい添付ファイルだけをすばやく取得しています。 – hmedia1
.... ....現在の方法では、ファイルが存在するかどうかをテストする前に、すべてのファイルに対してAPIリクエストを実行しています。 – hmedia1