Разработка парсера на PHP для 1С-Битрикс
PHP — естественный выбор для парсера, работающего в связке с 1С-Битрикс. Один язык, один рантайм, прямой доступ к API инфоблоков без промежуточных слоёв. Но PHP-парсер имеет ограничения, которые нужно учитывать при проектировании: однопоточность, лимиты памяти, отсутствие встроенного event loop.
Архитектура PHP-парсера
Парсер состоит из четырёх компонентов:
1. Конфигурация источников. Массив или таблица в БД с параметрами каждого источника: URL, тип (RSS, HTML, API), CSS-селекторы для извлечения данных, маппинг полей, частота обновления.
2. HTTP-клиент. Для простых задач — cURL через CHttpClient из ядра Битрикс или нативный curl_multi для параллельных запросов. Для сложных — Guzzle с middleware для retry, логирования, ротации прокси.
3. Парсер HTML/XML. DOMDocument + DOMXPath для точной навигации по DOM. Для CSS-селекторов — библиотека Symfony\Component\DomCrawler. Для RSS — SimpleXMLElement.
4. Импортёр. Слой записи данных в инфоблоки Битрикс через D7 API или старый API (CIBlockElement).
Базовая реализация
Минимальный парсер HTML-страницы на PHP:
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementTable;
Loader::includeModule('iblock');
function parseSource(string $url, array $selectors): array
{
$html = file_get_contents($url, false, stream_context_create([
'http' => [
'timeout' => 30,
'user_agent' => 'Mozilla/5.0 (compatible; SiteBot/1.0)',
],
]));
$dom = new DOMDocument();
@$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new DOMXPath($dom);
$items = [];
foreach ($xpath->query($selectors['list']) as $node) {
$title = $xpath->evaluate('string(' . $selectors['title'] . ')', $node);
$link = $xpath->evaluate('string(' . $selectors['link'] . ')', $node);
$items[] = ['title' => trim($title), 'link' => $link];
}
return $items;
}
Этот каркас работает, но не готов к продакшну. Нужна обработка ошибок, таймауты, логирование, дедупликация.
Параллельные запросы через curl_multi
Главное узкое место PHP-парсера — последовательность запросов. Загрузка 1 000 страниц по 2 секунды каждая = 33 минуты. С curl_multi_exec можно обрабатывать 10–20 запросов параллельно:
$multiHandle = curl_multi_init();
$handles = [];
foreach ($urls as $i => $url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_multi_add_handle($multiHandle, $ch);
$handles[$i] = $ch;
}
do {
$status = curl_multi_exec($multiHandle, $active);
curl_multi_select($multiHandle);
} while ($active > 0);
Ограничение: больше 50 параллельных соединений — и PHP начинает потреблять слишком много памяти. Для масштабного парсинга (10 000+ URL) разбивайте на батчи по 20–30 соединений.
Интеграция с ядром Битрикс
Преимущество PHP-парсера — прямой доступ к API. Не нужен REST, не нужна промежуточная база. Импорт в инфоблок:
$element = new CIBlockElement();
$elementId = $element->Add([
'IBLOCK_ID' => IBLOCK_CATALOG,
'NAME' => $parsedData['title'],
'XML_ID' => $parsedData['external_id'],
'ACTIVE' => 'Y',
'PREVIEW_TEXT' => $parsedData['description'],
'DETAIL_TEXT' => $parsedData['content'],
'DETAIL_TEXT_TYPE' => 'html',
'PREVIEW_PICTURE' => CFile::MakeFileArray($parsedData['image_path']),
]);
if ($elementId) {
CIBlockElement::SetPropertyValuesEx($elementId, IBLOCK_CATALOG, [
'SOURCE_URL' => $parsedData['url'],
'ARTICLE' => $parsedData['sku'],
]);
}
Важно: при массовом импорте отключайте поиск и обновление URL:
CIBlockElement::DisableEvents(); // Отключает обработчики событий
Без этого каждый Add() запускает переиндексацию поиска, обновление фасетного индекса и другие обработчики — импорт 10 000 товаров растянется на часы.
Обработка ошибок и устойчивость
PHP-парсер в продакшне должен обрабатывать:
-
Таймауты — сервер не отвечает, соединение зависло. Устанавливайте
CURLOPT_TIMEOUTиCURLOPT_CONNECTTIMEOUT. - HTTP-ошибки — 403, 429, 503. Для 429 (rate limit) — увеличьте задержку. Для 403 — смените прокси. Для 503 — повторите позже.
-
Некорректный HTML —
DOMDocument::loadHTMLгенерирует warnings. Подавляйте через@илиlibxml_use_internal_errors(true), но логируйте проблемные URL. -
Исчерпание памяти — большие HTML-страницы (5+ МБ) съедают память. Устанавливайте
memory_limitадекватно и освобождайте DOM после обработки:unset($dom).
Паттерн retry с экспоненциальной задержкой:
function fetchWithRetry(string $url, int $maxRetries = 3): ?string
{
for ($i = 0; $i < $maxRetries; $i++) {
$response = @file_get_contents($url);
if ($response !== false) {
return $response;
}
sleep(pow(2, $i)); // 1, 2, 4 секунды
}
return null;
}
Логирование
Без логов отладка парсера невозможна. Минимальный набор событий для записи:
- Начало и завершение сессии парсинга (время, количество обработанных URL).
- Каждый HTTP-запрос: URL, статус ответа, время загрузки.
- Ошибки парсинга: URL, тип ошибки, контекст.
- Результат импорта: создано, обновлено, пропущено (дубли), ошибки.
Используйте \Bitrix\Main\Diag\Logger из D7 или пишите в отдельную таблицу parser_log.
Когда PHP недостаточно
PHP-парсер не подходит, если:
- Нужен рендеринг JavaScript — SPA-сайты, динамическая подгрузка контента. Здесь нужен headless-браузер (Puppeteer/Playwright), а это Node.js или Python.
- Объём парсинга превышает 50 000 страниц за сессию — PHP упирается в однопоточность и потребление памяти.
- Требуется сложная обработка текста (NLP, классификация, извлечение сущностей) — экосистема Python значительно богаче.
В этих случаях рассмотрите гибридный подход: Python/Node.js для сбора данных, PHP для импорта в Битрикс.







