# DomCrawler: HTML/XML в данные

Восемь практических задач и 16 вариантов. Настоящие Symfony DomCrawler 7.4.22 и CssSelector 7.4.22, HTML5 parser 2.12.0. PHP 8.2+ с dom/mbstring, Composer2. На странице — интерактивное исследование сохранённого исполнения PHP. Браузер не запускает парсер, не исполняет HTML и не загружает введённые URL. Все данные вымышленные.

## Windows / PowerShell

Установите PHP и Composer из официальных источников, проверьте `php --version`, `php -m`, `composer --version`. В активном php.ini включите dom и mbstring; путь показывает `php --ini`. Далее из каталога проекта:

```powershell
composer install --no-interaction --no-plugins --prefer-dist
composer validate --strict
composer audit
composer capture
composer test
composer build-public
composer serve
```

Откройте http://127.0.0.1:8521. Остановить сервер — Ctrl+C в его терминале. `php -S` служит локальной проверке, не production. Для готовой записи vendor не нужен: достаточно раздавать public локальным HTTP-сервером, но PHP-проекты требуют install.

## Linux / Ubuntu или Debian

Проверяйте поддерживаемую версию PHP в репозитории своего выпуска. Пример установки модулей для текущего системного PHP:

```bash
sudo apt update
sudo apt install php-cli php-xml php-mbstring unzip ca-certificates
php --version
php -m
# Composer2 устанавливается по официальной инструкции getcomposer.org.
composer install --no-interaction --no-plugins --prefer-dist
composer capture
composer test
composer build-public
php -S 127.0.0.1:8521 -t public
```

Нужен PHP не ниже8.2; если дистрибутив даёт более старый, сначала выберите поддерживаемый PHP. Не запускайте composer от root. `composer.lock` фиксирует зависимости. Обновление выполняется отдельно с повторными тестами.

## Свой файл без браузера

`bin/extract.php` демонстрирует ограниченный импорт каталога: HTML UTF-8, максимум1MiB, карточки `article.service`, атрибут `data-id`, заголовок `h2`, цена `.price`. Он использует сценарий export, проверяет цену/ID/дубли, выдаёт JSON и ничего не отправляет в сеть.

```powershell
New-Item -ItemType Directory -Force .runtime | Out-Null
php bin/extract.php --input fixtures/cards.html --output .runtime/services.json
$LASTEXITCODE
```

```bash
mkdir -p .runtime
php bin/extract.php --input fixtures/cards.html --output .runtime/services.json
echo $?
```

Код0 — данные приняты;2 — пустая выборка или отклонённые записи, требуется проверка;1 — ошибка файла/выполнения. Даже при2 отчёт сохраняется, но использовать его как подтверждённую замену каталога нельзя. Без `--output` JSON идёт в stdout. Директория вывода должна существовать; запись заменяет указанный файл атомарным rename. Сначала сохраняйте отдельный отчёт, затем принимайте бизнес-решение об импорте.

Для своей разметки измените селекторы в сценарии, добавьте обезличенную фикстуру и тесты. Сохраните источник вне web-root. Не передавайте секретные страницы в публичную мастерскую. При XML используется LIBXML_NONET и отказ от DTD/ENTITY; это ограниченная политика нашей лаборатории, не обещание защиты произвольного XML-конвейера.

## Состав

- src/Lab.php — загрузка фикстур, HTML/XML, числа и CSV.
- scenarios/*.php —8 реальных задач.
- fixtures/ —14 HTML/XML-документов, включая Windows-1251.
- bin/capture.php —16 вариантов в recording.json.
- tests/run.php —проверки данных, границ и совпадения записи с выполнением.
- public/ —Bootstrap5.3.9, мастерская, записи, исходники для чтения.
- docs/LINUX-VPS.md —права, отдельный пользователь, systemd, публикация статики.

Записи Windows и Linux используют одни исходники; сравнивайте `cases` и `sourceHashes`, а не время генерации. После изменения PHP/фикстур выполните capture, test и build-public. Старый recording.json не станет результатом нового кода автоматически.

## Источники и лицензия

https://symfony.com/doc/7.4/components/dom_crawler.html
https://symfony.com/doc/7.4/components/css_selector.html
https://www.php.net/manual/en/class.domdocument.php
https://www.php.net/manual/en/function.mb-convert-encoding.php
https://getcomposer.org/doc/01-basic-usage.md

Код мастерской MIT; сторонние лицензии в public/THIRD-PARTY-LICENSES.txt. Производственный сервер и физический телефон этим CLI-тестом не проверяются.
