МойСклад — обмен по API с помощью Python
Документация по API МойСклад — https://dev.moysklad.ru/doc/api/remap/1.2/#mojsklad-json-api
Подключение к API МойСклад
В настройках МойСклад создаём токен:
Передаём токен и параметры headers в скрипт. Также в параметры URL можем передать условия и фильтры. Подробнее про фильтры в документации.
В нашем примере получим список товаров, изменённых в период с 10 по 12 июля.
import requests
token = 'наборцифрибуквполученныхвнастройкахмойсклад'
headers = {'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'}
params = [
("filter", "updated>=2019-07-10 12:00:00;updated<=2019-07-12 12:00:00")
]
url = "https://online.moysklad.ru/api/remap/1.2/entity/assortiment"
response = requests.get(url=url, headers=headers)
result = response.json()
print(result)
Получить ассортимент
Получить список всех товаров можно двумя способами:
- Обычным запросом с указанием фильтров, если нужна только часть ассортимента.
- Асинхронным запросом, если нужен весь ассортимент.
Получить часть ассортимента
В одном запросе можно получить не более 1000 позиций. Для этого используем параметры limit
и offset
. В нашем примере добавим в параметр фильтр по товарам, у которых нулевой остаток filter=stockMode=empty
.
url = "https://online.moysklad.ru/api/remap/1.2/entity/assortment"
limit = 1000
offset = 0
while True:
params = (
("limit", limit),
("offset", offset),
("filter", "stockMode=empty")
)
response = requests.get(url=url, headers=headers, params=params)
result = response.json()
offers = result["rows"]
if len(offers) == 0:
break
offset += limit
Получить весь ассортимент асинхронно
План такой:
- создаём задачу на формирование файла выгрузки всего ассортимента
- позже проверяем статус выполнения задачи
- если статус “DONE“, скачиваем файл выгрузки
Время формирования файла зависит от количества товаров. Для примера приведу метрики из моего опыта. Ассортимент из 45112 позиций формировался 20 минут и размер файла выгрузки составил 600 Мб.
Поэтому получать такой объем ассортимента удобнее асинхронной задачей, чем в обычном цикле.
1) Создаём асинхронную задачу. Для этого в url передадим параметр async=true
. Параметры limit
и offset
нам не нужны.
url = "https://online.moysklad.ru/api/remap/1.2/entity/assortment?async=true"
response = requests.get(url=url, headers=headers)
print(response.headers)
Результатом запроса будет созданная задача, а в заголовках два атрибута:
Location – URL результата выполнения Асинхронной задачи.
Content-Location – URL статуса Асинхронной задачи.
'Location': 'https://online.moysklad.ru/api/remap/1.2/async/138758d3-e566-11ec-0a80-0156005de0e5/result'
'Content-Location': 'https://online.moysklad.ru/api/remap/1.2/async/138758d3-e566-11ec-0a80-0156005de0e5'
2) Проверяем статус задачи
Отправляем запрос с URL
, полученным в 'Content-Location'
.
response_headers = {
'Location': 'https://online.moysklad.ru/api/remap/1.2/async/138758d3-e566-11ec-0a80-0156005de0e5/result',
'Content-Location': 'https://online.moysklad.ru/api/remap/1.2/async/138758d3-e566-11ec-0a80-0156005de0e5'
}
url = response_headers['Content-Location']
response = requests.get(url=url, headers=headers)
result = response.json()
print(result["state"])
3) Скачиваем файл выгрузки
url = "https://online.moysklad.ru/api/remap/1.2/async/1ff1d301-e3d8-11ec-0a80-0d43003c1135/result"
with open('assortiment.json', 'wb') as file:
response = requests.get(url=url, headers=headers, stream=True)
for chunk in response.iter_content(4096):
file.write(chunk)