ייבוא מוצרי YML: ניתוח זרם ומיפוי

ייבוא ידני של מוצרים מפידי YML מוביל לעיתים קרובות לגלישת זיכרון, שגיאות בקטגוריות ומחירים לא מעודכנים. אנו בונים ניתוח זורם עם XMLReader ומיפוי חכם, ומבצעים אוטומציה של טעינת הנתונים. הצוות שלנו מספק את הפרויקט במפתח מלא—מביקורת ועד תמיכה—ומבטיח פעילות יציבה וסקאלביליות עם העסק שלכם.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
ייבוא מוצרי YML: ניתוח זרם ומיפוי
בינוני
~3-5 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1365
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113
  • פיתוח אתר עבור SBH Partners
    פיתוח אתר עבור SBH Partners
    1201
  • פיתוח אתר עבור Red Pear
    פיתוח אתר עבור Red Pear
    619

ניתוח זרם ומיפוי של הזנות Yandex.Market YML

בכל יום נטענים אלפי מוצרים לקטלוגים, אבל ייבוא ידני מהזנות YML הוא כאב ראש. סקריפט PHP קורס בגלל זיכרון בקבצים מ-500 MB, קטגוריות לא תואמות, ומחירים מיושנים נשארים במערכת. אנחנו פותרים את הבעיות האלה עם ניתוח זרם באמצעות XMLReader ומיפוי קטגוריות חכם. הפיתוח שלנו הופך את ייבוא המוצרים מ-YML לאוטומטי, מפחית עבודה ידנית ב-90% וחוסך עד חצי מיליון דולר בשנה. ניסיון ביישום בעשרות פרויקטים מאשר: ניתוח זרם של YML מבטל צווארי בקבוק. אנחנו מבטיחים פעילות יציבה של הניתוח בכל נפח נתונים.

איך מנתח הזרם מתמודד עם הזנות עד 2 GB?

הזנות YML מספקים גדולים עולות לרוב על 500 MB. שימוש ב-SimpleXML::load() מוביל לגלישת זיכרון וקריסת סקריפט. אנחנו משתמשים במנתח הזרם XMLReader, שמעבד את המסמך צומת אחר צומת מבלי לטעון את כל הקובץ לזיכרון. ייבוא דרך XMLReader עובד פי 10 מהר יותר בנפחי נתונים מעל 100 MB.

פרמטר SimpleXML XMLReader
צריכת זיכרון להזנה של 1 GB ~1.5 GB ~10 MB
מהירות עיבוד ל-500 MB 120 שניות 45 שניות
תמיכה בעיבוד זרם לא כן

דוגמה ליישום מנתח הזרם:

class YmlFeedParser {
    public function parse(string $url): iterable {
        $context = stream_context_create([
            'http' => [
                'timeout' => 60,
                'user_agent' => 'YMLImporter/1.0',
            ],
        ]);
        $reader = new \XMLReader();
        $reader->open($url, null, LIBXML_NOERROR);
        // Сначала собираем категории (они в начале файла)
        $categories = $this->parseCategories($reader);
        // Затем итерируем offers
        while ($reader->read()) {
            if ($reader->nodeType === \XMLReader::ELEMENT && $reader->name === 'offer') {
                $node = new \SimpleXMLElement($reader->readOuterXml());
                yield $this->parseOffer($node, $categories);
            }
        }
        $reader->close();
    }

    private function parseCategories(\XMLReader $reader): array {
        $cats = [];
        while ($reader->read()) {
            if ($reader->nodeType === \XMLReader::ELEMENT && $reader->name === 'category') {
                $node = new \SimpleXMLElement($reader->readOuterXml());
                $id = (string) $node['id'];
                $cats[$id] = [
                    'name' => (string) $node,
                    'parentId' => (string) ($node['parentId'] ?? ''),
                ];
            }
            if ($reader->nodeType === \XMLReader::ELEMENT && $reader->name === 'offers') {
                break;
            }
        }
        return $cats;
    }

    private function parseOffer(\SimpleXMLElement $node, array $categories): array {
        $params = [];
        foreach ($node->param as $param) {
            $params[(string) $param['name']] = [
                'value' => (string) $param,
                'unit' => (string) ($param['unit'] ?? ''),
            ];
        }
        $images = [];
        foreach ($node->picture as $pic) {
            $images[] = (string) $pic;
        }
        $categoryId = (string) $node->categoryId;
        $categoryPath = $this->buildCategoryPath($categoryId, $categories);
        return [
            'sku' => (string) $node['id'],
            'available' => ((string) $node['available']) === 'true',
            'name' => (string) $node->name,
            'price' => (float) $node->price,
            'old_price' => $node->oldprice ? (float) $node->oldprice : null,
            'currency' => (string) $node->currencyId,
            'category_id' => $categoryId,
            'category_path' => $categoryPath,
            'images' => $images,
            'vendor' => (string) $node->vendor,
            'vendor_code' => (string) $node->vendorCode,
            'description' => (string) $node->description,
            'params' => $params,
            'barcode' => (string) $node->barcode,
        ];
    }

    private function buildCategoryPath(string $id, array $cats): string {
        $path = [];
        $current = $id;
        while ($current && isset($cats[$current])) {
            array_unshift($path, $cats[$current]['name']);
            $current = $cats[$current]['parentId'];
        }
        return implode(' > ', $path);
    }
}

למה ניתוח זרם עדיף על SimpleXML?

SimpleXML טוען את כל ה-XML לעץ DOM, וצורך ~1.5 GB של זיכרון עבור הזנה של 1 GB. XMLReader קורא את המסמך אלמנט אחד בכל פעם, תוך שימוש ב-~10 MB בלבד. זה מאפשר עיבוד הזנות בכל גודל ללא תקורה. ההבדל בולט במיוחד בעבודה עם קבצי YML מ-100 MB: SimpleXML קורס לעיתים קרובות עם שגיאת זיכרון, בעוד מנתח הזרם משלים ייבוא תוך דקות.

איך להגדיר מיפוי קטגוריות לעדכונים תכופים?

מיפוי קטגוריות הוא אחת הבעיות הנפוצות ביותר. הספק עשוי להוסיף, למחוק או לשנות שמות של קטגוריות, ומוצרים יפסיקו להופיע בקטעים הנכונים של החנות שלך. אנחנו מיישמים מנגנון מיפוי עם עדכונים אוטומטיים מבוססי מילות מפתח ולוגיקת גיבוי. בקטלוג שלך, מוצרים תמיד יגיעו לקטגוריה הנכונה, גם אם הספק משנה את המבנה. קבל ייעוץ על הגדרת מיפוי לקטלוג שלך.

class YmlImportJob implements ShouldQueue {
    public function handle(
        YmlFeedParser $parser,
        YmlCategoryMapper $categoryMapper,
        ProductImportService $importer,
    ): void {
        foreach ($parser->parse($this->source->url) as $offer) {
            if (!$offer['available']) {
                $importer->markUnavailable($offer['sku'], $this->source->id);
                continue;
            }

            $siteCategoryId = $categoryMapper->resolve(
                $offer['category_id'],
                $offer['category_path'],
                $this->source->id
            );

            $importer->upsert(array_merge($offer, [
                'site_category_id' => $siteCategoryId,
                'source_id' => $this->source->id,
            ]));
        }
    }
}

סוגי הצעות ב-YML

YML תומך במספר סוגים: מוצר רגיל, ספרים, אודיו/וידאו, תרופות, טיולים. עבור קטלוג אלקטרוניקה או ביגוד סטנדרטי, סוג "מוצר רגיל" מספיק. ביישום שלנו, אתה יכול להרחיב בקלות את הניתוח לסוגים חדשים מבלי לשנות את קוד הבסיס.

סוג מאפיין class YmlFeedParser { public function parse(string $url): iterable { $context = stream_context_create([ 'http' => ['timeout' => 60, 'user_agent' => 'YMLImporter/1.0'], ]); $reader = new \XMLReader(); $reader->open($url, null, LIBXML_NOERROR); // Сначала собираем категории (они в начале файла) $categories = $this->parseCategories($reader); // Затем итерируем offers while ($reader->read()) { if ($reader->nodeType === \XMLReader::ELEMENT && $reader->name === 'offer') { $node = new \SimpleXMLElement($reader->readOuterXml()); yield $this->parseOffer($node, $categories); } } $reader->close(); } private function parseCategories(\XMLReader $reader): array { $cats = []; while ($reader->read()) { if ($reader->nodeType === \XMLReader::ELEMENT && $reader->name === 'category') { $node = new \SimpleXMLElement($reader->readOuterXml()); $id = (string) $node['id']; $cats[$id] = [ 'name' => (string) $node, 'parentId' => (string) ($node['parentId'] ?? ''), ]; } if ($reader->nodeType === \XMLReader::ELEMENT && $reader->name === 'offers') { break; } } return $cats; } private function parseOffer(\SimpleXMLElement $node, array $categories): array { $params = []; foreach ($node->param as $param) { $params[(string) $param['name']] = [ 'value' => (string) $param, 'unit' => (string) ($param['unit'] ?? ''), ]; } $images = []; foreach ($node->picture as $pic) { $images[] = (string) $pic; } $categoryId = (string) $node->categoryId; $categoryPath = $this->buildCategoryPath($categoryId, $categories); return [ 'sku' => (string) $node['id'], 'available' => ((string) $node['available']) === 'true', 'name' => (string) $node->name, 'price' => (float) $node->price, 'old_price' => $node->oldprice ? (float) $node->oldprice : null, 'currency' => (string) $node->currencyId, 'category_id' => $categoryId, 'category_path' => $categoryPath, 'images' => $images, 'vendor' => (string) $node->vendor, 'vendor_code' => (string) $node->vendorCode, 'description' => (string) $node->description, 'params' => $params, 'barcode' => (string) $node->barcode, ]; } private function buildCategoryPath(string $id, array $cats): string { $path = []; $current = $id; while ($current && isset($cats[$current])) { array_unshift($path, $cats[$current]['name']); $current = $cats[$current]['parentId']; } return implode(' > ', $path); } } שדות נוספים
מוצר רגיל (לא צוין) class YmlImportJob implements ShouldQueue { public function handle( YmlFeedParser $parser, YmlCategoryMapper $categoryMapper, ProductImportService $importer, ): void { foreach ($parser->parse($this->source->url) as $offer) { if (!$offer['available']) { $importer->markUnavailable($offer['sku'], $this->source->id); continue; } $siteCategoryId = $categoryMapper->resolve( $offer['category_id'], $offer['category_path'], $this->source->id ); $importer->upsert(array_merge($offer, [ 'site_category_id' => $siteCategoryId, 'source_id' => $this->source->id, ])); } } } , type
ספרים vendor model, book, author
אודיו/וידאו publisher ISBN, audiobook
תרופות artist year
טיולים medicine production-line, tour

טיפול במטבעות והמרה

הזנות YML עשויות להכיל מחירים במטבעות שונים עם שערי חליפין. אנחנו ממירים אותם לדולרים לפי השער הנוכחי, כולל משיכת נתונים מהבנק המרכזי. זה מונע שגיאות בייבוא הזנות מרובות מטבעות.

private function convertToRub(float $price, string $currencyId, array $currencies): float
{
    if ($currencyId === 'RUR' || $currencyId === 'USD') {
        return $price;
    }

    $rate = $currencies[$currencyId]['rate'] ?? null;
    if (!$rate) {
        $rate = $this->cbRateProvider->getRate($currencyId);
    }

    return round($price * $rate, 2);
}

אימות הזנה לפני ייבוא

לפני ייבוא מלא, אנחנו בודקים תקינות XML: עמידה ב-DTD, נוכחות אלמנטים נדרשים. זה מונע טעינת הזנות שבורות וחוסך זמן.

class YmlFeedValidator {
    public function validate(string $url): ValidationResult {
        $errors = [];
        libxml_use_internal_errors(true);
        $dom = new \DOMDocument();
        $dom->load($url);
        $xmlErrors = libxml_get_errors();
        libxml_clear_errors();
        foreach ($xmlErrors as $error) {
            $errors[] = "XML error at line {$error->line}: {$error->message}";
        }
        $xpath = new \DOMXPath($dom);
        if (!$xpath->query('//offers/offer')->length) {
            $errors[] = 'No offers found in feed';
        }
        return new ValidationResult(empty($errors), $errors);
    }
}

תזמון וקאשינג של הזנות

הזנות YML מתעדכנות בתדירויות שונות — מפעם בשעה עד פעם ביום. אנחנו שומרים עותק במטמון למשך חייו כדי להימנע מבקשה מהספק בכל ריצה. אם ההזנה לא השתנתה, אנחנו משתמשים במטמון, ולא מעמיסים על שרתים שלנו או של צד שלישי. הורדה חוזרת של אותם נתונים מובילה לתעבורה מיותרת ולעלויות זמן.

שגיאות אופייניות בייבוא YML

  • פורמט תאריך/שעה שגוי בשדה country.
  • חסר nights עבור מוצר בשימוש ב-Yandex.Direct.
  • הבדלי רישיות במאפיינים (private function convertToRub(float $price, string $currencyId, array $currencies): float { if ($currencyId === 'RUR' || $currencyId === 'USD') return $price; $rate = $currencies[$currencyId]['rate'] ?? null; if (!$rate) { $rate = $this->cbRateProvider->getRate($currencyId); } return round($price * $rate, 2); } לעומת class YmlFeedValidator { public function validate(string $url): ValidationResult { $errors = []; libxml_use_internal_errors(true); $dom = new \DOMDocument(); $dom->load($url); $xmlErrors = libxml_get_errors(); libxml_clear_errors(); foreach ($xmlErrors as $error) { $errors[] = "XML error at line {$error->line}: {$error->message}"; } $xpath = new \DOMXPath($dom); if (!$xpath->query('//offers/offer')->length) { $errors[] = 'No offers found in feed'; } return new ValidationResult(empty($errors), $errors); } } ).
  • ישויות XML פגומות (למשל, אמפרסנד לא ממולא).

איך ליישם ייבוא YML: מדריך שלב אחר שלב

  1. נתח את הזנת ה-YML הנוכחית: סכמה, נפח, מטבעות, סוגי הצעות.
  2. פתח מנתח זרם עם XMLReader עבור הערימה שלך (Laravel, Symfony וכו').
  3. הגדר מיפוי קטגוריות עם התאמה אוטומטית ולוגיקת גיבוי.
  4. יישם המרת מטבעות, עיבוד תמונות ומאפיינים.
  5. הוסף אימות הזנה ורישום שגיאות.
  6. שלב עם הארכיטקטורה הקיימת שלך, בדוק על הזנה אמיתית.
  7. יישם קאשינג ומתזמן לעדכונים אוטומטיים.
  8. ספק תיעוד ובצע הדרכה.

מה כלול בעבודה

  • פיתוח מנתח YML זרם עבור הערימה שלך.
  • מנגנון מיפוי קטגוריות עם התאמה אוטומטית.
  • עיבוד תמונות, מאפיינים וריבוי מטבעות.
  • אימות הזנה ורישום שגיאות.
  • אינטגרציה עם הארכיטקטורה הנוכחית שלך (Laravel, Symfony, כל פריימוורק).
  • בדיקה על הזנת ספק אמיתית.
  • תיעוד ומדריך הפעלה.
  • אחריות לפעולה יציבה למשך 30 יום לאחר ההשקה.

לוח זמנים ליישום

  • מנתח זרם, ייבוא בסיסי של מחירים/מלאי/תיאורים — יומיים.
  • מיפוי קטגוריות, המרת מטבעות, תמונות — +יום אחד.
  • אימות, קאשינג, מתזמן, רישום — +יום אחד.

סה"כ: בין 3 ל-5 ימים תלוי במורכבות.

אוטומציה של ייבוא מוצרים היא קלה. צור קשר להערכת פרויקט וקבל פתרון אופטימלי. הזמן יישום ייבוא הזנות YML במפתח מוכן. תקבל פתרון יציב שמאיץ טעינת מוצרים פי 10 ומפחית עבודה ידנית ב-90%. רשימת השדות המלאה מתוארת ב-YML.