first commit
This commit is contained in:
commit
cfd3d9e81c
|
@ -0,0 +1,3 @@
|
|||
__pycache__
|
||||
.vscode
|
||||
result/
|
|
@ -0,0 +1,97 @@
|
|||
import requests
|
||||
import time
|
||||
import os
|
||||
import csv
|
||||
import pandas as pd
|
||||
|
||||
from ozon_data import headers
|
||||
|
||||
# URL для первого и второго запроса
|
||||
url_list = "https://api-seller.ozon.ru/v2/supply-order/list"
|
||||
url_get = "https://api-seller.ozon.ru/v2/supply-order/get"
|
||||
url_bundle = "https://api-seller.ozon.ru/v1/supply-order/bundle"
|
||||
|
||||
|
||||
order_state = [
|
||||
|
||||
"ORDER_STATE_DATA_FILLING",
|
||||
]
|
||||
|
||||
try:
|
||||
response_list = requests.post(
|
||||
url_list,
|
||||
headers=headers,
|
||||
json={
|
||||
"filter": {"states": order_state},
|
||||
"paging": {"from_supply_order_id": 0, "limit": 100},
|
||||
},
|
||||
)
|
||||
response_list.raise_for_status()
|
||||
data_list = response_list.json()
|
||||
|
||||
# print("Результат первого запроса:")
|
||||
# print(data_list)
|
||||
|
||||
order_ids = data_list.get("supply_order_id", [])
|
||||
|
||||
if not order_ids:
|
||||
print(data_list)
|
||||
raise ValueError(
|
||||
"Не удалось получить supply_order_id из ответа первого запроса"
|
||||
)
|
||||
|
||||
# Второй запрос
|
||||
response_get = requests.post(
|
||||
url_get, headers=headers, json={"order_ids": order_ids}
|
||||
)
|
||||
response_get.raise_for_status() # Проверка на ошибки
|
||||
data_get = response_get.json()
|
||||
|
||||
# print("Результат второго запроса:")
|
||||
print(data_get)
|
||||
|
||||
orders = data_get.get("orders", [])
|
||||
result = []
|
||||
for order in orders:
|
||||
all_bundle_ids = [supply.get("bundle_id") for supply in order.get("supplies", [])]
|
||||
|
||||
b_response = requests.post(
|
||||
url=url_bundle,
|
||||
json={"bundle_ids": all_bundle_ids, "limit": 100},
|
||||
headers=headers,
|
||||
)
|
||||
b_response.raise_for_status()
|
||||
b_result = b_response.json()
|
||||
|
||||
for b in b_result.get('items'):
|
||||
result.append({
|
||||
"supply_order_number": order.get("supply_order_number"),
|
||||
"creation_date": order.get("creation_date"),
|
||||
**b,
|
||||
})
|
||||
time.sleep(0.3)
|
||||
df = pd.DataFrame(result)
|
||||
# print("Результат:", result)
|
||||
output_dir = "result"
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Получаем имя текущего скрипта без расширения
|
||||
script_name = os.path.splitext(os.path.basename(__file__))[0]
|
||||
filename = '_'.join([script_name, *order_state])
|
||||
csv_filename = os.path.join(
|
||||
output_dir, f"{filename}_output.csv"
|
||||
)
|
||||
xls_filename = os.path.join(
|
||||
output_dir, f"{filename}_output.xlsx"
|
||||
)
|
||||
|
||||
df.to_csv(csv_filename, encoding="utf-8")
|
||||
df.to_excel(xls_filename)
|
||||
|
||||
print(f"Данные успешно сохранены в {csv_filename}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Ошибка при выполнении запроса: {e}")
|
||||
except ValueError as e:
|
||||
print(f"Ошибка обработки данных: {e}")
|
|
@ -0,0 +1,6 @@
|
|||
# Заголовки для авторизации и передачи данных
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Client-Id": "1355708",
|
||||
"Api-Key": "21a9f824-9bc3-422c-8fd1-86d6a6a13d54",
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
import requests
|
||||
import time
|
||||
import os
|
||||
import ast
|
||||
import pandas as pd
|
||||
|
||||
from ozon_data import headers
|
||||
|
||||
# URL для первого и второго запроса
|
||||
url_list = "https://api-seller.ozon.ru/v4/product/info/stocks"
|
||||
url_detail = "https://api-seller.ozon.ru/v4/product/info/attributes"
|
||||
product_type = "INVISIBLE"
|
||||
try:
|
||||
response_list = requests.post(
|
||||
url_list,
|
||||
headers=headers,
|
||||
json={
|
||||
"filter": {
|
||||
"visibility": product_type,
|
||||
},
|
||||
"limit": 100,
|
||||
},
|
||||
)
|
||||
response_list.raise_for_status()
|
||||
data_list = response_list.json()
|
||||
df_list = pd.DataFrame(data_list["items"])
|
||||
|
||||
df_list['stocks'] = df_list['stocks'].apply(
|
||||
lambda x: ast.literal_eval(x.replace("'", '"')) if isinstance(x, str) else x
|
||||
)
|
||||
stocks_df = pd.json_normalize(df_list['stocks'].str[0])
|
||||
|
||||
df_list = pd.concat([df_list, stocks_df], axis=1)
|
||||
|
||||
response_detail = requests.post(
|
||||
url_detail,
|
||||
headers=headers,
|
||||
json={
|
||||
"filter": {
|
||||
"product_id": df_list["product_id"].to_list(),
|
||||
},
|
||||
"limit": 1000
|
||||
},
|
||||
)
|
||||
response_detail.raise_for_status()
|
||||
data_detail = response_detail.json()
|
||||
|
||||
df_detail = pd.DataFrame(data_detail["result"])
|
||||
|
||||
# Объединяем по id и product_id
|
||||
df = pd.merge(
|
||||
df_detail,
|
||||
df_list,
|
||||
left_on="id",
|
||||
right_on="product_id",
|
||||
how="inner" # или 'left', 'right', 'outer' в зависимости от задачи
|
||||
)
|
||||
|
||||
|
||||
# print("Результат:", result)
|
||||
output_dir = "result"
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Получаем имя текущего скрипта без расширения
|
||||
script_name = os.path.splitext(os.path.basename(__file__))[0]
|
||||
filename = "_".join([script_name, product_type])
|
||||
csv_filename = os.path.join(output_dir, f"{filename}_output.csv")
|
||||
xls_filename = os.path.join(output_dir, f"{filename}_output.xlsx")
|
||||
|
||||
df.to_csv(csv_filename, encoding="utf-8")
|
||||
df.to_excel(xls_filename)
|
||||
|
||||
print(f"Данные успешно сохранены в {csv_filename}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Ошибка при выполнении запроса: {e}")
|
||||
print(e)
|
||||
except ValueError as e:
|
||||
print(f"Ошибка обработки данных: {e}")
|
|
@ -0,0 +1,110 @@
|
|||
import requests
|
||||
import time
|
||||
import os
|
||||
import pandas as pd
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Импортируем заголовки (Client-Id и Api-Key), должны быть в файле ozon_data.py
|
||||
from ozon_data import headers
|
||||
|
||||
# URL эндпоинтов
|
||||
url_analytics = "https://api-seller.ozon.ru/v1/analytics/data"
|
||||
url_product_list = "https://api-seller.ozon.ru/v3/product/info/list"
|
||||
|
||||
# Автоматически определяем даты: за последние 7 дней
|
||||
date_to = datetime.today().date()
|
||||
date_from = date_to - timedelta(days=7)
|
||||
|
||||
# Преобразуем даты в строку для запроса
|
||||
date_from_str = str(date_from)
|
||||
date_to_str = str(date_to)
|
||||
|
||||
# Тело запроса
|
||||
payload = {
|
||||
"date_from": date_from_str,
|
||||
"date_to": date_to_str,
|
||||
"dimension": ["sku"],
|
||||
"metrics": ["ordered_units", "hits_view_pdp"],
|
||||
"limit": 1000
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post(url_analytics, headers=headers, json=payload)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
# Парсим результат
|
||||
result_data = []
|
||||
for item in data.get("result", {}).get("data", []):
|
||||
dimensions = item.get("dimensions", [])
|
||||
metrics = item.get("metrics", [])
|
||||
|
||||
row = {
|
||||
"sku": dimensions[0].get("id") if len(dimensions) > 0 else None,
|
||||
"ordered_units": metrics[0] if len(metrics) > 0 else 0,
|
||||
"hits_view_pdp": metrics[1] if len(metrics) > 1 else 0,
|
||||
}
|
||||
result_data.append(row)
|
||||
|
||||
df = pd.DataFrame(result_data)
|
||||
|
||||
# --- Шаг 2: Запрашиваем названия товаров через /v3/product/info/list ---
|
||||
skus = df["sku"].dropna().astype(int).unique().tolist()
|
||||
|
||||
# Разбиваем на чанки по 1000 штук (если больше 1000)
|
||||
def chunked(lst, n):
|
||||
"""Разбивает список на части по n элементов"""
|
||||
return [lst[i:i + n] for i in range(0, len(lst), n)]
|
||||
|
||||
for chunk in chunked(skus, 1000): # Ozon позволяет до 1000 SKU за раз
|
||||
payload_products = {
|
||||
"sku": chunk
|
||||
}
|
||||
|
||||
try:
|
||||
response_products = requests.post(url_product_list, headers=headers, json=payload_products)
|
||||
response_products.raise_for_status()
|
||||
data_products = response_products.json()
|
||||
|
||||
if "items" not in data_products:
|
||||
print("Ошибка: В ответе нет ключа 'items'")
|
||||
continue
|
||||
|
||||
for item in data_products.get("items", []):
|
||||
el_sku = item["sources"][0]["sku"]
|
||||
if el_sku and "name" in item:
|
||||
df.loc[df['sku'] == str(el_sku), 'name'] = item['name']
|
||||
else:
|
||||
print("Ошибка в элементе товара — нет 'sku' или 'name':")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Ошибка запроса к /v3/product/info/list: {e}")
|
||||
if e.response:
|
||||
print("Текст ответа:", e.response.text)
|
||||
|
||||
# Добавляем колонку: конверсия заказов к показам * 100
|
||||
df["conversion_ordered_to_views (%)"] = (
|
||||
df["ordered_units"] / df["hits_view_pdp"] * 100
|
||||
).round(2)
|
||||
|
||||
# Создаем папку для вывода
|
||||
output_dir = "result"
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Имя файла на основе скрипта
|
||||
script_name = os.path.splitext(os.path.basename(__file__))[0]
|
||||
filename = f"{script_name}_analytics_conversion_{date_from_str}_{date_to_str}"
|
||||
csv_filename = os.path.join(output_dir, f"{filename}.csv")
|
||||
xls_filename = os.path.join(output_dir, f"{filename}.xlsx")
|
||||
|
||||
# Сохраняем
|
||||
df.to_csv(csv_filename, index=False, encoding="utf-8-sig")
|
||||
df.to_excel(xls_filename, index=False)
|
||||
|
||||
print(f"Данные успешно сохранены в {csv_filename}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Ошибка при выполнении запроса: {e}")
|
||||
except Exception as e:
|
||||
print(f"Ошибка обработки данных: {e}")
|
|
@ -0,0 +1,96 @@
|
|||
import os
|
||||
import requests
|
||||
import pandas as pd
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from ozon_data import headers
|
||||
|
||||
# URL API
|
||||
url = "https://api-seller.ozon.ru/v2/posting/fbo/list"
|
||||
|
||||
# Параметры для месяца
|
||||
year = 2025
|
||||
# Укажите нужный месяц (1-12)
|
||||
month = 1
|
||||
|
||||
# Определение первого и последнего дня месяца
|
||||
first_day = datetime(year, month, 1) # Первый день месяца
|
||||
last_day = first_day + relativedelta(
|
||||
months=1, days=-1
|
||||
) # Последний день текущего месяца
|
||||
|
||||
# Формируем строки дат в ISO формате
|
||||
since = first_day.isoformat() + "Z" # Формат: 2025-01-01T00:00:00Z
|
||||
to = last_day.isoformat() + "Z" # Формат: 2025-01-31T23:59:59.999Z
|
||||
# Тело запроса
|
||||
payload = {
|
||||
"dir": "ASC",
|
||||
"filter": {
|
||||
"since": since,
|
||||
# "status": "delivered",
|
||||
"to": to,
|
||||
}, # Укажите статус, если нужно
|
||||
"limit": 1000,
|
||||
"offset": 0,
|
||||
"with": {"analytics_data": True, "financial_data": True},
|
||||
}
|
||||
print(payload)
|
||||
try:
|
||||
# Выполнение запроса
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
response.raise_for_status()
|
||||
data_raw = response.json()
|
||||
# Составляем таблицу
|
||||
data = []
|
||||
for order in data_raw["result"]:
|
||||
for product in order["products"]:
|
||||
product_id = product["sku"]
|
||||
financial = [
|
||||
i
|
||||
for i in order["financial_data"]["products"]
|
||||
if i["product_id"] == product_id
|
||||
]
|
||||
financial = financial[0]
|
||||
row = {
|
||||
"order_id": order["order_id"],
|
||||
"order_number": order["order_number"],
|
||||
"status": order["status"],
|
||||
"created_at": order["created_at"],
|
||||
"product_sku": product["sku"],
|
||||
"product_name": product["name"],
|
||||
"offer_id": product["offer_id"],
|
||||
"quantity": product["quantity"],
|
||||
"price": financial["price"],
|
||||
"commission_amount": financial["commission_amount"],
|
||||
"payout": financial["payout"],
|
||||
"warehouse": order["analytics_data"]["warehouse_name"],
|
||||
}
|
||||
data.append(row)
|
||||
|
||||
# Преобразуем в DataFrame
|
||||
df = pd.DataFrame(data)
|
||||
|
||||
output_dir = "result"
|
||||
if not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir)
|
||||
|
||||
# Получаем имя текущего скрипта без расширения
|
||||
script_name = os.path.splitext(os.path.basename(__file__))[0]
|
||||
|
||||
# Указываем полный путь для файла
|
||||
csv_filename = os.path.join(
|
||||
output_dir, f"{'_'.join([script_name, str(month), str(year)])}_output.csv"
|
||||
)
|
||||
xls_filename = os.path.join(
|
||||
output_dir, f"{'_'.join([script_name, str(month), str(year)])}_output.xlsx"
|
||||
)
|
||||
|
||||
df.to_csv(csv_filename, encoding="utf-8")
|
||||
df.to_excel(xls_filename)
|
||||
|
||||
print(f"Таблица успешно экспортирована в {csv_filename}")
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Ошибка запроса: {e}")
|
||||
except Exception as e:
|
||||
print(f"Произошла ошибка: {e}")
|
Loading…
Reference in New Issue