ZARAHOME prod 1.0

This commit is contained in:
va1is 2025-08-05 13:58:30 +03:00
parent 29ae6da104
commit 242774afd3
2 changed files with 120 additions and 15 deletions

View File

@ -0,0 +1,23 @@
from openpyxl import Workbook
from os.path import isdir, abspath
from os import mkdir
# объект для сохранения спаршенных категорий в таблицы
class Recorder:
def __init__(self, records_folder="category_parsed"):
# проверяем наличие папки для сохранения таблиц
if not isdir(abspath('records_folder')):
mkdir(abspath("records_folder"))
self.record_folder = abspath("records_folder")
# запись и сохранение таблицы
def record(self, csv_name, table_data):
workbook = Workbook()
worksheet = workbook.active
for row in table_data:
worksheet.append(row)
workbook.save(f"{self.record_folder}/{csv_name}.xlsx")

View File

@ -1,23 +1,105 @@
# xlsx_recorder.py · расширен отправкой JSON
from openpyxl import Workbook from openpyxl import Workbook
from os.path import isdir, abspath, join
from os.path import isdir, abspath
from os import mkdir from os import mkdir
import re, json, math, logging, requests, os
# объект для сохранения спаршенных категорий в таблицы log = logging.getLogger("recorder")
# ─────────────────────── настройки ───────────────────────
SEND_JSON = True # отправка POST
SAVE_JSON = True # сохранять копию JSON
POST_URL = "http://localhost:3005/parser/data"
INVALID_CHARS = r'[<>:"/\\|*?]'
def sanitize_filename(name: str, repl: str = "_") -> str:
"""Удаляет/заменяет символы, запрещённые в именах файлов."""
clean = re.sub(INVALID_CHARS, repl, name)
return clean.split("?", 1)[0].strip()
# объект для сохранения спаршенных категорий
class Recorder: class Recorder:
def __init__(self, records_folder="category_parsed"): def __init__(self, records_folder="records_folder"):
# проверяем наличие папки для сохранения таблиц # создаём папку при необходимости
if not isdir(abspath('records_folder')): rf_abs = abspath(records_folder)
mkdir(abspath("records_folder")) if not isdir(rf_abs):
self.record_folder = abspath("records_folder") mkdir(rf_abs)
self.record_folder = rf_abs
# запись и сохранение таблицы # запись таблицы + JSON/POST
def record(self, csv_name, table_data): def record(self, csv_name, table):
workbook = Workbook() csv_name = sanitize_filename(csv_name)
worksheet = workbook.active
# ─── 1) сохраняем XLSX ─────────────────────────────
wb = Workbook()
ws = wb.active
for row in table:
ws.append(row)
xlsx_path = join(self.record_folder, f"{csv_name}.xlsx")
wb.save(xlsx_path)
log.info("XLSX saved → %s", xlsx_path)
for row in table_data: # ─── 2) формируем JSON (по утверждённым правилам) ──
worksheet.append(row) headers = table[0]
idx = {h: i for i, h in enumerate(headers)}
workbook.save(f"{self.record_folder}/{csv_name}.xlsx") items = []
for row in table[1:]:
# базовые поля
article = row[idx["Артикул"]]
partnumber = row[idx["PartNumber"]]
size_full = row[idx["Свойство: Размер"]].replace("\n", "<br/>")
price_raw = row[idx["Цена закупки"]]
price_int = math.ceil(float(price_raw))
clr_name_raw = row[idx["Свойство: Цвет"]]
clr_name = clr_name_raw.capitalize()
vis = row[idx["Наличие на сайте"]]
weight_gram = float(row[idx["Свойство: Вес(г)"]]) if row[idx["Свойство: Вес(г)"]] else 0.0
weight_kg = math.ceil(weight_gram / 1000) if weight_gram else 0
# составляем объект
variant = {
"status_id": 1,
"color": clr_name,
"sku": f"{article}-{partnumber}",
"size": size_full,
"cost": price_int,
"originalUrl": row[idx["Краткое описание"]], # url_full в таблице
"originalName": row[idx["Название товара или услуги"]].capitalize(),
"originalDescription": (
row[idx["Полное описание"]].replace("\n", "<br/>") + "<br/>" +
row[idx["Параметр: Уход"]].replace("\n", "<br/>") + "<br/>" +
row[idx["Параметр: Происхождение"]].replace("\n", "<br/>")
).strip("<br/>"),
"originalComposition": row[idx["Параметр: Состав"]].replace("\n", "<br/>"),
"images": [img for img in row[idx["Изображения варианта"]].split("\n") if img],
"inStock": vis == "SHOW",
"weight": weight_kg
}
category_name = re.sub(INVALID_CHARS, "_",
row[idx["Размещение на сайте"]]
.replace("Каталог/ZaraHome/", ""))
items.append({
"category": {"name": category_name},
"variant": variant,
"brand": {"name": "zara-home"}
})
payload = {"items": items, "parserName": "zara-home"}
# ─── 3) сохраняем JSON при необходимости ───────────
if SAVE_JSON:
json_path = join(self.record_folder, f"{csv_name}.json")
with open(json_path, "w", encoding="utf-8") as fh:
json.dump(payload, fh, ensure_ascii=False, indent=2)
log.info("JSON saved → %s", json_path)
# ─── 4) POST на локальный сервис ───────────────────
if SEND_JSON:
try:
resp = requests.post(POST_URL, json=payload, timeout=20)
resp.raise_for_status()
log.info("POST %s OK (%s items)", csv_name, len(items))
except Exception as err:
log.warning("POST %s FAILED: %s", csv_name, err)