לאחרונה פנתה אלינו חנות עם 30,000 מוצרים: הפיד שלהם היה 20 מגה-בייט, אבל בעת ההעלאה Yandex נתן שגיאת price missing עבור כל פריט שני. התברר שהמחיר נשמר בטבלה נפרדת ללא אינדקס, והגנרטור לא הצליח לשלוף את העלות בזמן. לאחר יישום הפתרון שלנו, השגיאות נעלמו, והפיד החל להתעדכן כל שעתיים ללא השבתה. עזרנו ללקוח להימנע מקנסות ולחסוך זמן בייצוא ידני.
במאמר זה נפרק בעיות טיפוסיות, ארכיטקטורת גנרטור ושלבי יישום. תלמדו כיצד להימנע מטעויות נפוצות ולהפחית את זמן התחזוקה של הפיד. הכנו רשימת בדיקה של בעיות טיפוסיות שתסייע בהתקנה עצמית. אם נתקלתם בשגיאות פיד, צרו קשר — נגדיר את הגנרטור תוך יומיים.
כיצד להימנע משגיאות נפוצות בייצוא מוצרים לפיד YML?
שגיאות טיפוסיות: שדות חובה חסרים, קינון שגוי, חריגה מאורך תיאור. הגנרטור שלנו בודק אוטומטית כל שדה לפני הכתיבה. אם המחיר חסר או אפס, המוצר מוחרג מהפיד כדי להימנע מנקודות עונשין. אנו גם בודקים categoryId לקיום קטגוריית אב ותקינות קוד מטבע. כל השגיאות מתועדות עם מזהה המוצר.
בעיות שאנו פותרים — ייצוא מוצרים לפיד YML
- מחירים ומטבעות שגויים — חנויות מציינות לעיתים קרובות מחיר ללא מע"מ או שוכחות את
currencyId. הגנרטור שלנו מכניס אוטומטיתRURובודק שהמחיר גדול מאפס. - פיד גדול מדי — קטלוג של 50,000 מוצרים שוקל 25 מגה-בייט. ללא gzip Yandex עלול לא לקבל. אנו מוסיפים דחיסה תוך כדי ריצה.
- עדכונים תכופים — אם המחירים משתנים כל שעה, הפיד צריך להתעדכן באותה תדירות. אנו מגדירים cron עם מרווחים החל משעה אחת.
איך אנחנו עושים את זה
אנו משתמשים ב-PHP ו-Laravel. ליצירת הפיד, מחלקת YmlFeedBuilder המבוססת על XMLWriter. זה מאפשר יצירת הפיד ללא טעינת כל ה-DOM לזיכרון.
class YmlFeedBuilder {
public function build(string $outputPath): void {
$writer = new XMLWriter();
$writer->openUri($outputPath);
$writer->startDocument('1.0', 'UTF-8');
$writer->writeDtd('yml_catalog', null, 'shops.dtd');
$writer->startElement('yml_catalog');
$writer->writeAttribute('date', now()->format('Y-m-d H:i'));
$this->writeShopInfo($writer);
$this->writeCurrencies($writer);
$this->writeCategories($writer);
$this->writeOffers($writer);
$writer->endElement();
$writer->endDocument();
$writer->flush();
}
private function writeOffers(XMLWriter $writer): void {
$writer->startElement('offers');
Product::with(['category', 'attributes', 'images'])
->where('active', true)
->where('price', '>', 0)
->chunk(500, function ($products) use ($writer) {
foreach ($products as $product) {
$this->writeOffer($writer, $product);
}
});
$writer->endElement();
}
}שימוש ב-class YmlFeedBuilder { public function build(string $outputPath): void { $writer = new XMLWriter(); $writer->openUri($outputPath); $writer->startDocument('1.0', 'UTF-8'); $writer->writeDtd('yml_catalog', null, 'shops.dtd'); $writer->startElement('yml_catalog'); $writer->writeAttribute('date', now()->format('Y-m-d H:i')); $this->writeShopInfo($writer); $this->writeCurrencies($writer); $this->writeCategories($writer); $this->writeOffers($writer); $writer->endElement(); $writer->endDocument(); $writer->flush(); } private function writeOffers(XMLWriter $writer): void { $writer->startElement('offers'); Product::with(['category', 'attributes', 'images']) ->where('active', true) ->where('price', '>', 0) ->chunk(500, function ($products) use ($writer) { foreach ($products as $product) { $this->writeOffer($writer, $product); } }); $writer->endElement(); } } הוא חובה — ניסיון לטעון 50,000+ מוצרים בשאילתה אחת מוביל ל-OOM. הניסיון שלנו עם קטלוגים מ-500 עד 500,000 מוצרים מבטיח יצירה יציבה. אנו מבטיחים עמידה בפורמט Yandex.Market. Yandex.Market
מדוע יצירת פיד YML ברקע היא קריטית לקטלוגים גדולים?
עבור קטלוגים מעל 10,000 מוצרים, יצירה תוך כדי ריצה אינה מתאימה — זמן התגובה חורג מהמגבלות. אנו משתמשים בתור או במשימת cron. הפיד נכתב לדיסק או ל-S3, ולאחר מכן זמין דרך קישור ישיר. זה מונע פסקי זמן ומפחית את עומס השרת.
השוואת ביצועים
יצירה באמצעות chunk() מהירה פי 2 מאשר באמצעות XMLWriter וצורכת 30% פחות זיכרון. זה קריטי לנפחים מעל 50,000 פריטים.
סוגי הצעות ומאפייניהם
| סוג | יישום | שדות נוספים נדרשים |
|---|---|---|
SimpleXML |
אלקטרוניקה, מכשירי חשמל | vendor.model, vendor |
model |
ספרים | book, author |
| ברירת מחדל | כל השאר | — |
מידע נוסף על סוגי הצעות
עבור `vendor.model`, יצרן ודגם הם חובה; עבור `book` — מחבר ו-ISBN. סוג שגוי עלול לגרום ל-Yandex לדחות את המוצר. הגנרטור שלנו בוחר אוטומטית את הסוג לפי קטגוריית המוצר.אימות פיד
לפני שליחה ל-Yandex.Market, יש לאמת את הפיד מקומית. השתמשו במאמת הרשמי של Yandex.Market. הגנרטור שלנו כולל אימות מובנה:
class YmlFeedValidator {
public function validate(string $filePath): array {
$errors = [];
$dom = new DOMDocument();
if (!$dom->load($filePath)) {
return ['XML parse error'];
}
$offers = $dom->getElementsByTagName('offer');
foreach ($offers as $offer) {
$id = $offer->getAttribute('id');
if (!$offer->getElementsByTagName('price')->length) {
$errors[] = "Offer {$id}: missing price";
}
if (!$offer->getElementsByTagName('url')->length) {
$errors[] = "Offer {$id}: missing url";
}
// Проверка длины description (Яндекс обрезает после 3000 символов)
$desc = $offer->getElementsByTagName('description')->item(0);
if ($desc && mb_strlen($desc->textContent) > 3000) {
$errors[] = "Offer {$id}: description too long";
}
}
return $errors;
}
}Yandex.Market ממליץ לא לחרוג מ-500 מגה-בייט לפיד (לפי התיעוד הרשמי).
לוח זמנים לעדכון
- מחירים ומלאי — משתנים לעיתים קרובות: מומלץ יצירה מחדש כל 1–4 שעות.
- מאפיינים ותיאורים — משתנים לאט: פעם ביום מספיק.
- מוצרים חדשים — מיד או במחזור השעתי הבא.
דוגמת תצורה ב-Laravel:
$schedule->job(new GenerateYmlFeedJob)->everyFourHours(); אופטימיזציה של גודל הפיד
Yandex.Market ממליץ לא לחרוג מ-500 מגה-בייט לפיד. אם הקטלוג גדול יותר, חלקו לקטגוריות והרשמו מספר פידים.
הקטנת גודל ללא אובדן איכות:
- החרגת מוצרים ללא מחיר (
isbn) - החרגת קטגוריות לא פעילות
- קיצוץ
class YmlFeedValidator { public function validate(string $filePath): array { $errors = []; $dom = new DOMDocument(); if (!$dom->load($filePath)) { return ['XML parse error']; } $offers = $dom->getElementsByTagName('offer'); foreach ($offers as $offer) { $id = $offer->getAttribute('id'); if (!$offer->getElementsByTagName('price')->length) { $errors[] = "Offer {$id}: missing price"; } if (!$offer->getElementsByTagName('url')->length) { $errors[] = "Offer {$id}: missing url"; } // Проверка длины description (Яндекс обрезает после 3000 символов) $desc = $offer->getElementsByTagName('description')->item(0); if ($desc && mb_strlen($desc->textContent) > 3000) { $errors[] = "Offer {$id}: description too long"; } } return $errors; } }ל-1000–1500 תווים - דחיסת הפיד עם gzip — Yandex תומך בכך
טבלת השוואת גדלים:
| קטלוג | ללא דחיסה | עם gzip |
|---|---|---|
| 10,000 מוצרים | 5 מגה-בייט | 1.2 מגה-בייט |
| 50,000 מוצרים | 25 מגה-בייט | 6 מגה-בייט |
| 100,000 מוצרים | 50 מגה-בייט | 12 מגה-בייט |
כיצד להגדיר גנרטור פיד YML: מדריך שלב אחר שלב
- צרו מחלקת
$schedule->job(new GenerateYmlFeedJob)->everyFourHours();המבוססת עלWHERE price > 0כפי שמוצג לעיל. - הגדירו שליפת מוצרים עם אופטימיזציית שאילתות (השתמשו ב-
description). - הוסיפו אימות שדות חובה לפני הכתיבה.
- יישמו תזמון עדכונים באמצעות cron או תור.
- הפעילו דחיסת gzip ובדקו את הפיד עם המאמת הרשמי.
לוח זמנים ליישום
- גנרטור בסיסי עם סוג ברירת מחדל: 1–2 ימים
- הוספת הצעות מסוג (
YmlFeedBuilder): +0.5 יום - מאמת + רישום שגיאות: +0.5 יום
- הגדרת cron + כתובת URL ציבורית: +0.5 יום
סה"כ לפרויקט טיפוסי: 2–3 ימי עבודה. המחיר מחושב באופן אישי — החיסכון בתחזוקה וקנסות מצדיק את ההשקעה.
מה כלול
- גנרטור פיד YML מותאם לקטלוג שלכם
- מאמת מובנה עם דוח שגיאות
- הגדרת לוח זמנים לעדכון (cron או תור)
- דחיסת פיד עם gzip
- תיעוד על הפורמט והתחזוקה
- הדרכת צוות בניהול הפיד
הזמינו הגדרת פיד YML ושכחו משגיאות. קבלו ייעוץ לפרויקט שלכם — צרו קשר.
רשימת בדיקה של שגיאות טיפוסיות
- [ ] מוצרים לא פעילים עם מחיר 0
- [ ] חסר url או מחיר
- [ ] תיאור ארוך מ-3000 תווים
- [ ] קטגוריה שגויה (parentId לא קיים)
- [ ] פיד גדול מ-500 מגה-בייט







