Уявіть: ви запустили парсинг каталогу з 10 000 товарів, через годину дивитеся — імпортувалося всього 300. Без логів — гадання: чи джерело повернуло порожню сторінку, чи XPath зламався, чи ліміт пам'яті PHP закінчився на 50 000-му товарі. З логами — одразу бачите, що на 501-му товарі впав memory limit за 128 МБ. Налаштування структурованого логування — не розкіш, а необхідність для будь-якого проєкту з автонаповненням. Наш досвід показує, що правильна конфігурація скорочує час розбору інциденту з годин до хвилин. На одному проєкті ми прискорили пошук помилок у 6 разів, впровадивши єдиний формат з контекстом і ротацією. Розберемо, як організувати логи так, щоб не витрачати час на гадання.
"Без контексту логи — це шум. Ми перестали гадати, коли додали контекст у кожен виклик." — Іван, провідний розробник проєкту з 5000+ сутностей.
Рівні логування
Використовуйте стандартні рівні PSR-3, навіть якщо не підключаєте Monolog. Рівні керують обсягом інформації, що записується:
- DEBUG — кожен HTTP-запит до джерела, час відповіді, розмір body. Вмикається лише під час налагодження через прапорець в адмінці.
- INFO — старт/стоп парсера, кількість оброблених елементів, кількість створених/оновлених записів в інфоблоці.
- WARNING — пропущений елемент (не пройшов валідацію), повільна відповідь джерела (>5 сек), повторна спроба запиту.
- ERROR — виняток під час парсингу, помилка запису в b_iblock_element, невалідна відповідь API.
У продакшні тримайте рівень INFO. Перемикання на DEBUG — через налаштування в b_option або файл /local/parser_debug.flag, без перезапуску та деплою. Ця гнучкість дозволяє безпечно діагностувати проблеми на живому проєкті.
Куди писати логи: файл, b_event_log чи кастомна таблиця?
Вибір сховища залежить від інтенсивності парсингу та вимог до аналітики. Порівняємо варіанти:
| Критерій |
Файлова система |
b_event_log |
Кастомна таблиця |
| Простота інтеграції |
Висока (fopen) |
Середня (API Бітрікс) |
Низька (міграція) |
| Продуктивність при 1000 записів/хв |
Відмінно |
Погано (гальмує) |
Добре |
| Пошук і фільтрація |
grep/awk |
Адмінка |
SQL-запити |
| Ротація |
logrotate |
Не потрібна |
Налаштовується |
| Аналітичні звіти |
Скриптами |
Обмежено |
Будь-які |
Файлова система. Пишемо в /local/logs/parser/YYYY-MM-DD.log. Формат рядка: [2024-03-15 14:23:01] INFO | source=competitor_a | action=update | iblock_id=12 | element_id=45678 | duration=0.34s. Кожен рядок — одна подія. Роздільник | зручний для grep і awk. Обов'язкові поля: timestamp, level, source, action. Ротація — через logrotate або власний агент, що видаляє файли старші 30 днів. Без ротації логи DEBUG-рівня за тиждень легко займуть гігабайти.
Таблиця b_event_log. Штатний журнал Бітрікс. Виклик CEventLog::Add() з параметрами. Плюс — перегляд через адмінку, фільтрація, доступ для менеджерів без SSH. Мінус — таблиця не розрахована на тисячі записів за хвилину, при інтенсивному парсингу гальмує. Тому b_event_log використовуйте для WARNING і ERROR, а DEBUG пишіть у файл.
Кастомна таблиця. Створюємо таблицю parser_log з полями id, created_at, level, source, action, element_id, message, context (JSON). Індекс по (created_at, level, source). Це оптимальний варіант для проєктів, де парсер — критична підсистема, і потрібні аналітичні запити по логах. Наприклад, можна швидко порахувати кількість помилок за джерелами за останню годину.
Що важливіше: рівень чи контекст?
Рядок «Помилка парсингу» марний. Корисний рядок: «XPath //div[@class="price"]/span повернув 0 вузлів, очікувалося 1, URL: https://source.com/product/123, HTTP 200, body size: 45KB». Контекст дозволяє відтворити проблему без повторного запуску. Мінімальний контекст для кожного рівня:
| Рівень |
Обов'язковий контекст |
| DEBUG |
URL, HTTP-код, час відповіді, розмір body, User-Agent |
| INFO |
Джерело, дія, ID елемента інфоблоку, результат (created/updated/skipped) |
| WARNING |
Джерело, URL, причина пропуску, значення поля, очікуваний формат |
| ERROR |
Все вище плюс stack trace, memory_get_peak_usage(), вміст $arFields |
Як налаштувати клас ParserLogger?
Створіть клас ParserLogger у /local/php_interface/classes/ (або в просторі імен вашого модуля). Інтерфейс:
ParserLogger::info('import', [
'source' => 'competitor_a',
'element_id' => 45678,
'action' => 'update',
'fields_changed' => ['PRICE', 'QUANTITY'],
]);
Всередині — запис у файл + у b_event_log для рівнів WARNING і вище. Перемикання рівня — через COption::GetOptionString('parser', 'log_level', 'INFO'). Цей підхід дає єдину точку конфігурації.
Покрокова інструкція з впровадження ParserLogger
- Створіть файл
/local/php_interface/classes/ParserLogger.php з namespace Bitrix\Parser.
- Реалізуйте методи debug(), info(), warning(), error() з сигнатурою
function (string $action, array $context = []).
- У кожному методі формуйте рядок логу і пишіть у файл через
error_log з прапором FILE_APPEND.
- Для WARNING і ERROR додатково викликайте
CEventLog::Add().
- Додайте метод
setLevel($level), що читає з COption.
- Автозавантаження класу пропишіть у
init.php.
Як моніторити помилки автоматично?
Логи самі по собі не допоможуть, якщо їх ніхто не читає. Додайте агент, що запускається кожні 15 хвилин, який рахує кількість ERROR-записів за період. Якщо поріг перевищено, надсилайте сповіщення (поштова подія або Telegram). Це перетворює логування з пасивного інструменту на активну систему моніторингу. На практиці ми бачили, як такий агент допоміг запобігти простою інтернет-магазину: помилка через зміну структури HTML на сайті джерела була помічена через 3 хвилини, а не через 3 години.
Що входить у налаштування логування під ключ
Ми пропонуємо комплексне налаштування логування для вашого проєкту:
- Клас
ParserLogger з рівнями DEBUG/INFO/WARNING/ERROR і автоматичним записом у файл і b_event_log.
- Файлові логи з ротацією в
/local/logs/parser/ (зберігання 30 днів).
- Можливість перемикання рівня через адмінку без деплою.
- Агент моніторингу помилок зі сповіщеннями.
- Документація з використання та інструкція для команди.
Ми працюємо з Бітріксом більше 10 років, реалізували 50+ проєктів з автонаповненням та інтеграцією 1С. Гарантуємо, що після налаштування ви зможете розбирати будь-яку помилку парсера за хвилини. Оцінимо ваш проєкт безкоштовно — зв'яжіться, щоб обговорити деталі. Замовте налаштування логування під ключ і економте години на налагодженні.
З чого почати розробку парсера для 1С-Бітрікс?
XMLReader, а не SimpleXML — вибір інструмента визначає долю проекту. SimpleXML завантажує весь XML у пам’ять, і при файлі постачальника на 800 МБ PHP впаде з fatal error на ліміті 512 МБ. XMLReader обробляє потоково, node за node, споживаючи 20–30 МБ — в 30 разів ефективніше. З цієї деталі стартує будь-яка розробка парсерів під Бітрікс. Ми робимо такі системи вже понад 10 років, реалізували 50+ проектів, і жоден не обходиться без правильного вибору парсера.
Проблеми, які вирішує парсинг
- Первинне наповнення каталогу — 15 000 карток з описами, характеристиками, фото. Вручну це три місяці контент-менеджера; парсер — тиждень з налагодженням. Економія часу — до 90%.
- Моніторинг цін конкурентів — збір даних з Ozon, Wildberries, сайтів конкурентів. Конкурент знизив ціну на ходову позицію — дізнаєтеся через дві години, а не через два тижні. Окупається за 2–3 місяці.
- Агрегація постачальників — п’ять прайсів у різних форматах (CSV з CP1251, XML у CommerceML, Excel з об’єднаними комірками) перетворюються на єдиний каталог із загальною системою властивостей інфоблоку.
- Збагачення карток — підтягуємо характеристики, інструкції, 3D-моделі з сайтів виробників. Без цього картка товару — пустушка для SEO.
- Оновлення асортименту — товари, які зникли з фіду постачальника, деактивуються через
CIBlockElement::Update($ID, ['ACTIVE' => 'N']). Нові — створюються. Каталог синхронізовано.
Інструменти для розробки парсерів
Статичні сайти — PHP (Goutte, Symfony DomCrawler) або Python (Scrapy, lxml). Швидкість: 50–100 сторінок/сек. Вистачає для каталогів без JS-рендерингу.
SPA та динамічні сайти — Puppeteer або Playwright. Нескінченний скрол, AJAX-фільтри, lazy-load картинок — headless-браузер все це обробить. Швидкість падає до 1–10 сторінок/сек, але альтернативи немає: дані існують лише після виконання JavaScript.
Файли постачальників:
- Excel (XLS, XLSX) — PhpSpreadsheet. Обережно з об’єднаними комірками та формулами — вони ламають автоматичний мапінг.
- CSV —
fgetcsv() з правильною кодуванням. Постачальники люблять CP1251, BOM у UTF-8 та крапку з комою замість коми. Все це потрібно детектувати та обробляти.
- XML/YML — XMLReader для великих файлів, SimpleXML для фідів до 50 МБ.
- CommerceML — стандартний формат обміну з 1С. Розбираємо
import.xml та offers.xml, мапимо на структуру інфоблоків.
API — REST-ендпоінти постачальників, API маркетплейсів (Ozon Seller API, Wildberries API). Працюємо в рамках rate limits, обробляємо пагінацію.
Як влаштований пайплайн автонаповнення?
Чотири етапи. Кожен може зламатися по-своєму.
-
Збір. Парсер обходить джерела по cron-розкладу. Сирі дані пишемо в проміжну таблицю — не одразу в b_iblock_element. Логуємо все: скільки сторінок обійшли, скільки елементів розпарсили, де отримали 403 або timeout. Без логів налагодження парсера — ворожіння на кавовій гущі.
-
Нормалізація. Тут основна робота:
- Очищення HTML-тегів, зайвих пробілів, Unicode-сміття
- Одиниці виміру: «мм» → «мм», «millimeters» → «мм», «миллиметр» → «мм»
- Мапінг категорій постачальника → розділи інфоблоку Бітрікс. В одного постачальника «Ноутбуки», в іншого «Ноутбуки та планшети», у третього «Laptops» — все в одну секцію
- Дедуплікація за артикулом, EAN/GTIN. Один товар від трьох постачальників не повинен з’явитися тричі
-
Завантаження в Бітрікс. Через CIBlockElement::Add() для нових елементів, CIBlockElement::Update() для існуючих. Зображення: завантажуємо, ресайзимо через CFile::ResizeImageGet(), конвертуємо в WebP. Властивості — через CIBlockElement::SetPropertyValuesEx(). SEO-мета через \Bitrix\Iblock\InheritedProperty\ElementValues. ЧПУ генеруємо з транслітерації назви.
-
Оновлення. Ключовий момент — не затерти ручні правки контент-менеджера. Оновлюємо лише ціну, залишки, активність. Опис та фото, доопрацьовані вручну, позначаємо прапорцем UF_MANUAL_EDIT у властивостях елемента і пропускаємо при імпорті. Товари, що зникли з фіду — деактивуємо, але не видаляємо.
Моніторинг цін конкурентів: необхідність та реалізація
Окрема підсистема зі своєю специфікою:
| Параметр |
Як влаштовано |
| Частота |
Від разу на день до кожних 2 годин — залежить від волатильності ринку |
| Зіставлення |
За артикулом, EAN, нечітке порівняння назв через відстань Левенштейна |
| Зберігання |
Своя таблиця vendor_price_monitor з історією, не інфоблоки |
| Алерти |
Telegram/email при відхиленні ціни конкурента більш ніж на X% |
| Автоправила |
«Тримати ціну на 3% нижче мінімальної серед конкурентів, але не нижче собівартості + 15%» |
Результат — дашборд: ваш товар vs конкуренти, історія цін, тренди. Менеджер бачить, де можна підняти ціну без втрати позиції, а де потрібно реагувати.
Модуль імпорту CSV/XML: налаштування під ваш формат
Для файлів від постачальників — кастомний модуль з адмінкою:
- Налаштовуваний мапінг: «колонка B у файлі → властивість BRAND інфоблоку»
- Автодетект кодування (CP1251, UTF-8, UTF-16) через
mb_detect_encoding() з перевіркою
- Завантаження зображень за URL з чергою агентів Bitrix — щоб не забити канал
- Інкрементальне оновлення за хешем рядка: змінився рядок — оновлюємо, ні — пропускаємо
- Cron-розклад, звіт: створено 145, оновлено 892, помилок 3 (з деталями)
Великі файли: CSV обробляємо батчами по 1000 рядків через fgetcsv(), XML потоково через XMLReader, фонове виконання через чергу агентів Бітрікс — ніяких PHP-таймаутів.
Правова сторона — що важливо врахувати
-
robots.txt — поважаємо. Crawl-delay — дотримуємося.
- Частота запитів — 1–2 в секунду, не більше. Не потрібно DDoS-ити чужий сайт.
- Контент виробників — використовуємо. Унікальні авторські тексти — не копіюємо.
- Персональні дані — не збираємо.
Що входить в розробку парсера під ключ?
| Складова |
Опис |
| Прототип |
Парсер 1–2 джерел за 2–3 дні для оцінки якості даних |
| Основний парсер |
Повний збір даних з одного джерела (статичний/динамічний) |
| Модуль імпорту в Бітрікс |
Нормалізація, завантаження, оновлення, адмінка мапінгу |
| Моніторинг цін |
Якщо потрібно – система збору та алертів (до 10 конкурентів) |
| Документація |
Опис архітектури, інструкція з оновлення селекторів |
| Підтримка |
Гарантія 3 місяці на безперебійну роботу, правка при зміні верстки донора |
Скільки часу займає розробка парсера?
Процес і терміни:
-
Прототип — парсер для 1–2 джерел за 2–3 дні. Оцінюємо якість даних, підводні камені (захист Cloudflare, капча, динамічне підвантаження).
-
Розробка — повний пайплайн: парсер → нормалізація → імпорт в Бітрікс → адмінка для управління.
-
Тестування — проганяємо на повному обсязі каталогу, перевіряємо edge-кейси (порожні поля, кривий HTML, биті картинки).
-
Запуск — налаштовуємо cron, моніторинг помилок через Telegram-бот.
-
Підтримка — конкурент переробив верстку? Оновлюємо CSS-селектори в парсері.
Орієнтовні терміни для різних типів завдань
| Задача |
Терміни |
| Парсер одного сайту (статичний HTML) |
3–5 днів |
| Парсер SPA-сайту (Puppeteer/Playwright, обхід захисту) |
1–2 тижні |
| Модуль імпорту CSV/XML в Бітрікс |
1–2 тижні |
| Система моніторингу цін (5–10 конкурентів) |
2–4 тижні |
| Комплексна система автонаповнення |
4–8 тижнів |
| Підтримка та адаптація парсерів |
за підпискою |
Отримайте консультацію: розкажіть про своє джерело даних — ми підберемо оптимальний підхід. Зв’яжіться для оцінки вашого проекту — запропонуємо рішення під ваш бюджет. Гарантуємо стабільну роботу парсерів і повну підтримку.