Разработка парсера на Python для 1С-Битрикс
Python выбирают для парсинга, когда PHP упирается в ограничения: нужен headless-браузер, асинхронная обработка тысяч URL, машинное обучение для классификации контента или работа с антибот-защитой. Обратная сторона — Python не имеет прямого доступа к API Битрикс, поэтому между парсером и CMS всегда есть промежуточный слой.
Почему Python, а не PHP
Конкретные причины, а не абстрактные преимущества:
-
Асинхронность.
asyncio+aiohttpпозволяют обрабатывать 100+ параллельных запросов в одном потоке. PHPcurl_multiограничен 20–50 параллельными соединениями на практике. - Headless-браузер. Playwright для Python — зрелый инструмент с полной поддержкой Chromium, Firefox, WebKit. PHP-обёртки для Puppeteer существуют, но значительно менее стабильны.
-
NLP и ML. Классификация текстов, извлечение сущностей, определение языка — библиотеки
spaCy,transformers,langdetectне имеют аналогов в PHP. -
Библиотеки для парсинга.
BeautifulSoup,lxml,Scrapy— проверенные временем инструменты с огромным сообществом.
Архитектура
Парсер на Python для Битрикс работает как отдельный сервис, взаимодействующий с CMS через один из каналов передачи данных:
[Python Parser] → [Промежуточное хранилище] → [PHP-импортёр → Битрикс]
Варианты промежуточного хранилища:
| Способ | Когда использовать | Плюсы | Минусы |
|---|---|---|---|
| JSON-файлы | До 1 000 элементов | Просто, нет зависимостей | Не масштабируется |
| PostgreSQL/MySQL | 1 000–100 000 | Транзакции, индексы | Нужна общая БД |
| REST API Битрикс | Любой объём | Прямая запись в CMS | Медленно (HTTP overhead) |
| Redis/RabbitMQ | Потоковая обработка | Асинхронность, очереди | Усложнение инфраструктуры |
Для большинства проектов оптимален вариант с общей базой данных: Python пишет в промежуточные таблицы, PHP-скрипт читает и импортирует в инфоблоки.
Реализация на Scrapy
Scrapy — фреймворк для парсинга, который берёт на себя очереди URL, retry, throttling, middleware. Структура проекта:
bitrix_parser/
├── scrapy.cfg
├── bitrix_parser/
│ ├── spiders/
│ │ ├── catalog_spider.py
│ │ └── news_spider.py
│ ├── items.py
│ ├── pipelines.py
│ ├── middlewares.py
│ └── settings.py
Spider для парсинга каталога:
import scrapy
class CatalogSpider(scrapy.Spider):
name = 'catalog'
start_urls = ['https://example.com/catalog/']
def parse(self, response):
for product in response.css('.product-card'):
yield {
'name': product.css('h2::text').get(),
'price': product.css('.price::text').get(),
'description': product.css('.desc::text').get(),
'image': product.css('img::attr(src)').get(),
'url': product.css('a::attr(href)').get(),
}
next_page = response.css('.pagination .next::attr(href)').get()
if next_page:
yield response.follow(next_page, self.parse)
Pipeline для записи в базу Битрикс:
import psycopg2
class BitrixPipeline:
def open_spider(self, spider):
self.conn = psycopg2.connect(
host='localhost', port=5433,
dbname='bitrix_db', user='bitrix'
)
def process_item(self, item, spider):
cursor = self.conn.cursor()
cursor.execute("""
INSERT INTO parser_staging (name, price, description, image_url, source_url, status)
VALUES (%s, %s, %s, %s, %s, 'new')
ON CONFLICT (source_url) DO UPDATE SET
price = EXCLUDED.price,
updated_at = NOW()
""", (item['name'], item['price'], item['description'],
item['image'], item['url']))
self.conn.commit()
return item
Асинхронный парсинг с aiohttp
Для задач, где Scrapy избыточен (простые API, RSS-фиды), асинхронный подход на aiohttp:
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url, timeout=aiohttp.ClientTimeout(total=30)) as resp:
return await resp.text()
async def parse_all(urls):
connector = aiohttp.TCPConnector(limit=50)
async with aiohttp.ClientSession(connector=connector) as session:
tasks = [fetch(session, url) for url in urls]
return await asyncio.gather(*tasks, return_exceptions=True)
50 параллельных соединений обрабатывают 10 000 URL за 5–10 минут — против 5–6 часов при последовательной загрузке.
Headless-браузер для SPA
Сайты на React, Vue, Angular отдают пустой HTML. Playwright решает это:
from playwright.async_api import async_playwright
async def parse_spa(url):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url, wait_until='networkidle')
content = await page.content()
await browser.close()
return content
Ресурсоёмкость: каждый экземпляр Chromium потребляет 100–300 МБ RAM. Для массового парсинга используйте пул из 3–5 экземпляров и очередь задач.
Передача данных в Битрикс
PHP-скрипт на стороне Битрикс забирает данные из промежуточной таблицы:
$rows = $DB->Query("SELECT * FROM parser_staging WHERE status = 'new' LIMIT 100");
while ($row = $rows->Fetch()) {
$elementId = (new CIBlockElement())->Add([
'IBLOCK_ID' => CATALOG_IBLOCK_ID,
'NAME' => $row['name'],
'XML_ID' => md5($row['source_url']),
// ...
]);
if ($elementId) {
$DB->Query("UPDATE parser_staging SET status='imported', bx_id={$elementId} WHERE id={$row['id']}");
}
}
Этот скрипт запускается по cron каждые 5–15 минут и обрабатывает новые записи пакетами.
Деплой и мониторинг
Python-парсер деплоится отдельно от Битрикс:
- Systemd-сервис или cron для запуска по расписанию.
-
Virtual environment (
venv) — изоляция зависимостей от системного Python. -
Логирование — модуль
loggingс ротацией файлов или отправкой в syslog. - Мониторинг — скрипт проверяет, что парсер отработал за последние N часов, и отправляет алерт при зависании.
Типичный crontab:
0 1 * * * cd /opt/parsers && /opt/parsers/venv/bin/scrapy crawl catalog 2>> /var/log/parser.log
0 */4 * * * cd /opt/parsers && /opt/parsers/venv/bin/python news_parser.py 2>> /var/log/parser.log
Когда выбирать Python
| Критерий | PHP | Python |
|---|---|---|
| Простой парсинг RSS/XML | Лучший выбор | Избыточен |
| JavaScript-рендеринг | Ограниченно | Playwright/Selenium |
| 10 000+ URL за сессию | Сложно | asyncio/Scrapy |
| Классификация контента | Нет инструментов | spaCy, transformers |
| Прямой импорт в Битрикс | Нативно | Через промежуточный слой |
Python-парсер оправдан при сложных источниках, большом объёме или потребности в обработке текста. Для простых задач PHP-парсер проще в поддержке — одна кодовая база, один стек.







