[СДЕЛАЙ САМ] Импорт товаров MiniShop2 из xml фида Яндекс.Маркета
Приветствую! За последний месяц второй раз прилетает задача сделать импорт товаров из фида Яндекс.Маркета. Может быть я не один такой, поэтому делюсь своим решением.
Возможности
1. Импорт дерева категорий (ВАЖНО! категории в файле должны быть расположены сверху вниз в порядке увеличения уровня вложенности);
2. Импорт товаров (*есть возможность указать соответствие полей товара в файле и на сайте в свойстве конфигурации «productFields»);
3. Импорт опций товаров из тэгов «param» (опции создаются автоматически);
4. Импорт галереи товаров из тэгов «picture»;
5. Импорт производителей (*есть возможность указать соответствие полей производителя в файле и на сайте в свойстве конфигурации «vendorFields»);
*если нужно передать значение для которого не предусмотрен отдельный тэг, то следует использовать тэг param, при этом в качестве соответствия нужно указывать содержимое атрибута «name» с префиксом «name_». Например вы хотите передать логотип производителя
Импорт других сущностей не поддерживается, но при желании можете дописать.
Быстрый старт
1. Скачать из этого репозитория файлы «importfeed.class.php» и «importconfig.inc.php».
2. Выставить необходимые настройки в файле «importconfig.inc.php».
3. Установить компонент ExtraFields и создать с его помощью поле «feed_id».
4. Запустить через терминал или по CRON файл «importfeed.class.php», используя php>= 7.4.
Особенности
1. Скачанные файлы должны находится в папке «core/elements» иначе нужно менять путь к корневому файлу «index.php»;
2. В конфигурации установлен шаг в 100 ресурсов, его можно изменить, но это способно привести к ошибке с нехваткой памяти при большом количестве товаров. Рекомендую повесить запуск на крон и ставить ша не более 500.
3. Пока работает скрипт не удаляйте файл readingdata.json в нём хранится информация о последней завершённой итерации. Данный файл будет автоматически удалён после завершения всех импортов.
4. После завершения всех импортов будет создан файл importfinished.txt, который не позволит запустить импорт повторно в автоматическом режиме. Соответственно, если нужно запустить импорт снова, удалите этот файл.
5. Ресурсы создаются без использования процессоров, поэтому никакие плагины на события типа OnDocFormSave и других не сработают. Так сделано для ускорения процесса и потому что задача не обязывала использовать процессоры.
6. Все фото добавленные в галерею будут удалены из исходной папки, потому что дубли никому не нужны.
Возможные ошибки.
1. Дубли в названиях могут привести к ошибке превышения объёма памяти или «Segmentation fault» (чтобы это ни значило). Есть два варианта решения, либо вручную исправить проблемные названия, либо в файле конфигурации установить свойству «createUniquePagetitle» значение true.
2. Проблемы с загрузкой картинок в формате WEBP. Галерея минишопа выдаёт ошибку «Не верный формат файла». Добавление формата в разрешённые в источнике файлов проблему не решило.
Отслеживание ошибок.
В скрипт встроено подробное логирование, информация о ходе выполнения пишется в файл «import_log.txt». так же скрипт можно выполнять поэтапно задав начальную и конечную позицию в файле «readingdata.json».
Поблагодарить автора, а также немного порадовать других активных участников сообщества можно, отправив донат одним из следующих способов
Возможности
1. Импорт дерева категорий (ВАЖНО! категории в файле должны быть расположены сверху вниз в порядке увеличения уровня вложенности);
2. Импорт товаров (*есть возможность указать соответствие полей товара в файле и на сайте в свойстве конфигурации «productFields»);
3. Импорт опций товаров из тэгов «param» (опции создаются автоматически);
4. Импорт галереи товаров из тэгов «picture»;
5. Импорт производителей (*есть возможность указать соответствие полей производителя в файле и на сайте в свойстве конфигурации «vendorFields»);
*если нужно передать значение для которого не предусмотрен отдельный тэг, то следует использовать тэг param, при этом в качестве соответствия нужно указывать содержимое атрибута «name» с префиксом «name_». Например вы хотите передать логотип производителя
<param name="ЛогоВендора">https://art-sites.ru//assets/components/phpthumbof/cache/logo-icon-w.4113b3f984c288dac851d68881c111ed.webp</param>
в этом случае в свойстве «vendorFields» должна быть такая запись'vendorFields' => [
...
'logo' => 'name_ЛогоВендора',
...
]
Импорт других сущностей не поддерживается, но при желании можете дописать.
Быстрый старт
1. Скачать из этого репозитория файлы «importfeed.class.php» и «importconfig.inc.php».
2. Выставить необходимые настройки в файле «importconfig.inc.php».
3. Установить компонент ExtraFields и создать с его помощью поле «feed_id».
4. Запустить через терминал или по CRON файл «importfeed.class.php», используя php>= 7.4.
Особенности
1. Скачанные файлы должны находится в папке «core/elements» иначе нужно менять путь к корневому файлу «index.php»;
2. В конфигурации установлен шаг в 100 ресурсов, его можно изменить, но это способно привести к ошибке с нехваткой памяти при большом количестве товаров. Рекомендую повесить запуск на крон и ставить ша не более 500.
3. Пока работает скрипт не удаляйте файл readingdata.json в нём хранится информация о последней завершённой итерации. Данный файл будет автоматически удалён после завершения всех импортов.
4. После завершения всех импортов будет создан файл importfinished.txt, который не позволит запустить импорт повторно в автоматическом режиме. Соответственно, если нужно запустить импорт снова, удалите этот файл.
5. Ресурсы создаются без использования процессоров, поэтому никакие плагины на события типа OnDocFormSave и других не сработают. Так сделано для ускорения процесса и потому что задача не обязывала использовать процессоры.
6. Все фото добавленные в галерею будут удалены из исходной папки, потому что дубли никому не нужны.
Возможные ошибки.
1. Дубли в названиях могут привести к ошибке превышения объёма памяти или «Segmentation fault» (чтобы это ни значило). Есть два варианта решения, либо вручную исправить проблемные названия, либо в файле конфигурации установить свойству «createUniquePagetitle» значение true.
2. Проблемы с загрузкой картинок в формате WEBP. Галерея минишопа выдаёт ошибку «Не верный формат файла». Добавление формата в разрешённые в источнике файлов проблему не решило.
Отслеживание ошибок.
В скрипт встроено подробное логирование, информация о ходе выполнения пишется в файл «import_log.txt». так же скрипт можно выполнять поэтапно задав начальную и конечную позицию в файле «readingdata.json».
Поблагодарить автора, а также немного порадовать других активных участников сообщества можно, отправив донат одним из следующих способов
- На карту Тинькофф www.tinkoff.ru/sl/2V9U9RrcJZP
- На YooMoney yoomoney.ru/fundraise/RPkkYwNcL7A.230131
- На Qiwi кошелек qiwi.com/p/77012827737
- Казахстан Каспи по номеру +7 701 282 77 37
Поблагодарить автора
Отправить деньги
Комментарии: 43
Будет ли работать если фид на стороннем сайте? Умеет ли обновлять уже загруженные товары? Подтянет ли фото со стороннего сайта? Зачем нужен feed_id?
Будет ли работать если фид на стороннем сайте?Будет, фид сначала скачивается на ваш сервер.
Умеет ли обновлять уже загруженные товары?Если название в фиде и pagetitle на сайте совпадают, то да.
Подтянет ли фото со стороннего сайта?Фото тянутся исключительно по полной ссылке, даже если они на вашем сервере лежат, они должны быть доступны по ссылке вида domain.ru/imagename.jpg
Зачем нужен feed_id?По нему определяется вложенность категорий и принадлежность товара к категории
В какую настройку прописывать поле изображений? Несколько изображений он загрузит? в ms2gallery?
Пjле изображений это всегда picture.
так?
'productFields' => [
'weight' => 'name_Вес',
'pagetitle' => 'name',
'content' => 'description',
'made_in' => 'country_of_origin',
'price' => 'price',
'old_price' => 'oldprice',
'picture' => 'picture',
],
'productFields' => [
'weight' => 'name_Вес',
'pagetitle' => 'name',
'content' => 'description',
'made_in' => 'country_of_origin',
'price' => 'price',
'old_price' => 'oldprice',
'picture' => 'picture',
],
А что это? Поля товара? Если да, то нет указывать там picture не надо
Да. А где тогда указывать?
Нигде, автоматом картинки берутся если они есть.
Отлично!
все скачал и настроил но не работает и выдает ошибку синтаксиса
PHP Parse error: syntax error, unexpected 'ModX' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST)
по этим строкам public ModX $modx;
public string $basepath;
public string $logpath;
public string $feedPath;
public string $imagePath;
public string $finishFilePath;
public string $readingDataPath;
public array $config;
public array $options;
PHP 7.4 modx 2.8.5
PHP Parse error: syntax error, unexpected 'ModX' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST)
по этим строкам public ModX $modx;
public string $basepath;
public string $logpath;
public string $feedPath;
public string $imagePath;
public string $finishFilePath;
public string $readingDataPath;
public array $config;
public array $options;
PHP 7.4 modx 2.8.5
Точно запускаешь с php 7.4?
Ага.
PHP модуль Apache 7.4.29 (alt)
Сразу полез проверять т.к. подумал что просто не поддерживается версией php
PHP модуль Apache 7.4.29 (alt)
Сразу полез проверять т.к. подумал что просто не поддерживается версией php
Покажи команду которой запускаешь скрипт?
/opt/php72/bin/php /var/www/u1145459/data/www/glav-site.ru/core/elements/importfeed.class.php > /dev/null 2>&1
или
/opt/php72/bin/php /var/www/u1145459/data/www/glav-site.ru/core/elements/importfeed.class.php
по крону.
и
php /var/www/u1145459/data/www/glav-site.ru/core/elements/importfeed.class.php
/opt/php72/bin/php /var/www/u1145459/data/www/glav-site.ru/core/elements/importfeed.class.php
из ssh
или
/opt/php72/bin/php /var/www/u1145459/data/www/glav-site.ru/core/elements/importfeed.class.php
по крону.
и
php /var/www/u1145459/data/www/glav-site.ru/core/elements/importfeed.class.php
/opt/php72/bin/php /var/www/u1145459/data/www/glav-site.ru/core/elements/importfeed.class.php
из ssh
Ну дык ты запускаешь с версией 7.2
вот же. И там все команды такие. ща попробую перезапустить под 74. Спасибо
Поменял версию. Тишина. и в журнале. Срипт куда логи пишет? Скрипт точно подтягивает настройки из importconfig.inc.php, но дальше где-то падает.
Срипт куда логи пишет?Сюда
запускается файл создает, лог пишет, но не может скачать файл. В чем может быть причина? файл открывается в браузере нормально. В настройках importconfig.inc.php где можно накосячить чтобы не скачивался?
Нашел
Запустить удалось. Пишет в лог следующее:
13.07.2023 18:06:49 [ImportFeed::start] Начат импорт товаров.
13.07.2023 18:06:49 [ImportFeed::startReading] Импортируем ресурс с порядковым номером 1
13.07.2023 18:06:49 [ImportFeed::startReading] memory usage: 8,9995651245117
13.07.2023 18:06:49 [ImportFeed::createResource] Будет обработан ресурс со следующими данными.Array
(
[feed_id] => 36120
)
13.07.2023 18:06:49 [ImportFeed::createResource] Будет обработан ресурс со следующими данными.Array
(
[feed_id] => 36120
[pagetitle] => Ресурс 1689260809
[alias] => resurs-1689260809
)
Импорт не происходит в итоге.
сам xml максимально упростил
<?xml version="1.0" encoding="UTF-8"?>
<shop>
<categories>
<category id="36120">Спальня</category>
</categories>
<offers>
<offer id="89" group_id="89" available="false">
<price>7600.00</price>
<categoryId>36120</categoryId>
<name>Прикроватная тумба Лофт Панара</name>
</offer>
</offers>
</shop>
В какую сторону копать?
Во-первых проверить настройки. Во-вторых, поле feed_id у ресурсов есть?
Да. Все это было. проблема оказалась в категориях.Их не было и импорт тормозил на этом этапе. Включил создание категорий. Теперь все работает, спасибо!
А есть Вариант привязать изображения к ms2Gallery. Сейчас грузит в стандартную галерею минишопа.
Конечно есть, надо переписать метод который грузит картинки так, чтобы он грузил в ms2Gallery
спасибо. Нашел переписал
Добрый день! Обычный XML не подойдет? Только YML?
Нет, там же вполне определенные тэги, только переписывать.
Нашел причину почему не грузит с удаленного сервера фид. importfeed.class.php 76 строка опечатка feelUrl
Добрый день! Возник вопрос, а как Выцепить id из Фида? . Вот этот 999 имеется ввиду
Если речь про id оффера, то для него нужно создать поле feed_id
Это уже создано. Он при импорте записывается. Тут вопрос немного другой получактая. Там сейчас идет проверка существует ли объект на сайте по pagetitle. А нужно по id. Я так понимаю нужно переписать строку про где newObject, проверив по if (! $id = товар с feed_id)?
Вот тут поле поменять надо
Ага. Я про неё и имел ввиду. Заменяем pagetitle на feed_id, а ресурс на $id(предварительно получив его $id = $item->attributes()->id)?
Не понимаю о каком ресурсе речь
В этой строке resource.
А почему ты хочешь положить объект класса modResource в переменную с именем id?
Видать я неправильно прочитал код. Тогда возвращаюсь к вопросу как получить id оффера для поиска товара с таким feed_id на сайте.
чтобы условие
if (!$resource = $this->modx->getObject($data['class_key'], ['pagetitle' => $data['feed_id']])) {
$resource = $this->modx->newObject($data['class_key']);
}
работало?
Я думал $id = $item->attributes()->id. я получу атрибут оффера.
$id = $xml->offer['id'];
или
$id = $item->offer['id'];
чтобы условие
if (!$resource = $this->modx->getObject($data['class_key'], ['pagetitle' => $data['feed_id']])) {
$resource = $this->modx->newObject($data['class_key']);
}
работало?
Я думал $id = $item->attributes()->id. я получу атрибут оффера.
$id = $xml->offer['id'];
или
$id = $item->offer['id'];
if (!$resource = $this->modx->getObject($data['class_key'], ['feed_id' => $data['feed_id']])) {
$resource = $this->modx->newObject($data['class_key']);
}
Даже так? Благодарю Артур, большой вы человек!
Привет, Артур! Спасибо тебе за твои труды. Есть вопрос по п.3: Импорт опций товаров из тэгов «param» (опции создаются автоматически). Правильно ли я понимаю, чтобы сопоставить уже созданные опции на своём сайте с param из xml, нужно переименовывать param'ы в файле xml? или это можно сделать через importconfig.inc.php? Если в будущем добавлять новые товары из того же xml, то придется каждый раз переименовывать все param?
И второй вопрос: тут уже задавался про обновление по id из фида, но я бы хотел обновлять товары не по id, а по vendorCode, для этого у меня в каждом товаре создано дополнительное поле sku. Как можно поменять обновление по этому ключу?
И второй вопрос: тут уже задавался про обновление по id из фида, но я бы хотел обновлять товары не по id, а по vendorCode, для этого у меня в каждом товаре создано дополнительное поле sku. Как можно поменять обновление по этому ключу?
Скрипт был рассчитан на импорт товаров на пустой сайт, поэтому опции и категории создаются автоматически. Если опции уже есть на сайте, то param должны иметь такие же имена как и ключи у опций на сайте. Если param имеют другие имена, то надо модифицировать скрипт, а именно метод importProducts.
Не знаю кто пустил слух, что товары импортируются по feed_id, на самом деле они импортируются по pagetitle, по feed_id определяется родитель. Чтобы сделать импорт товаров по sku, а импорт категорий по pagetitle, надо модифицировать функцию manageResource.
Не знаю кто пустил слух, что товары импортируются по feed_id, на самом деле они импортируются по pagetitle, по feed_id определяется родитель. Чтобы сделать импорт товаров по sku, а импорт категорий по pagetitle, надо модифицировать функцию manageResource.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.