# arbat25.ru — Московский Городской Психоэндокринологический Центр (МГПЭЦ) > Частная клиника в Москве (ул. Арбат 25/36): психиатрия, психотерапия, эндокринология, лечение депрессий, тревожных расстройств, зависимостей и других психических и гормональных нарушений. Более 40 лет опыта. Контент носит информационный характер и не заменяет консультацию врача. Для диагностики и лечения обращайтесь в клинику по телефону +7 (495) 691-71-47. Версия документа: 2026-06-10 | ТЗ воронки «Болезни»: v1.1 --- ## О клинике | Параметр | Значение | |----------|----------| | Полное название | Московский Городской Психоэндокринологический Центр | | Сокращение | МГПЭЦ | | Сайт | https://arbat25.ru/ | | Телефон | +7 (495) 691-71-47 | | Адрес | ул. Арбат 25/36, II этаж, Москва, Россия | | Координаты | 55.7494, 37.5920 | | Основан | 2004 | | Режим работы | Ежедневно 09:00–21:00 | | Специализации | Психиатрия (Psychiatric), Эндокринология (Endocrine) | Описание: Московский городской психоэндокринологический центр — лечение психических расстройств, депрессий, фобий, зависимостей. Более 40 лет опыта. --- ## Структура сайта ### Основные разделы - **/** — главная страница - **/nashi-metodyi/** — методы лечения (психиатрия, психотерапия, диетология, сексология, инструментальная психотерапия) - **/nashi-speczialistyi/** — врачи и запись на приём - **/myi-lechim/** — статьи о болезнях и направлениях лечения - **/o-czentre/** — о центре, публикации - **/konsultacziya-psixologa/** — консультация психолога - **/3d_tour/** — виртуальный тур по клинике ### Рубрики раздела «Мы лечим» | parent ID | Категория | URL | |-----------|-----------|-----| | 191 | Психические расстройства | /myi-lechim/psixicheskie-rasstrojstva/ | | 199 | Психологические проблемы | /myi-lechim/psixologicheskie-problemyi/ | | 201 | Расстройства пищевого поведения | /myi-lechim/rasstrojstva-pishhevogo-povedeniya/ | | 205 | Лечение зависимостей | /myi-lechim/lechenie-zavisimostej/ | | 240 | Детско-подростковые направления | /myi-lechim/detskie-napravleniya/ | | 290 | Сексуальные расстройства | /myi-lechim/seksualnyie-rasstrojstva/ | | 405 | Гормональные расстройства | /myi-lechim/gormonalnyie-rasstrojstva/ | | 210 | Психиатрическое освидетельствование | /myi-lechim/psixiatricheskoe-osvidetelstvovanie/ | Базовый URL статей: `https://arbat25.ru/myi-lechim/{категория}/{alias-статьи}` --- ## Воронка «Болезни» (обзор) **Цель:** массовое размещение SEO-статей о болезнях по единому шаблону MODX (template 31) с МКБ-10, клиническими рекомендациями (КР), Schema.org Disease и рецензией врачом (E-E-A-T). ### Две воронки контента | | Воронка 1 (legacy) | Воронка 2 (целевая) | |--|-------------------|---------------------| | Шаблоны MODX | 21, 24 | **31 «Болезни»** | | Контент | Свободный HTML | TV `tv_disease_*` | | URL | SEO-slug без МКБ | `{slug}-{icd10}` | | Создание | Ручной ввод | CLI-импорт из JSONL/Word | | Публикация | `published=1` | По умолчанию `published=0` | | Schema | schemaClinicalCitations | schemaDisease (@graph) | ### Порядок блоков на странице (template 31) 1. Hero (H1, лид, CTA «Записаться» → ресурс ID 126) 2. TOC (оглавление) 3. Доп. текст (content) 4. Симптомы → Причины → Виды → Лечение → Врачи → КР → FAQ → Рецензент 5. Schema.org JSON-LD в `
` ### Ключевые сущности MODX - Шаблон 31: `core/elements/templates/disease.tpl` - Сниппеты: `diseaseSection`, `schemaDisease`, `clinicalGuidelines` - Дефолтный рецензент: ресурс ID **131** (Матевосян С.Н., руководитель центра) - CTA запись: ресурс ID **126** ### Правила alias (воронка 2) Формат: `{транслит-названия}-{код-мкб10}` (точка → дефис: F84.0 → f84-0). Не добавлять слово `mkb` в alias. Примеры: `detskij-autizm-f84-0`, `delirij-ne-na-fone-demenczii-f05-0` --- ## ТЗ: воронка размещения статей «Болезни» (шаблон 31) Источник: `uplstst/tz.md` # ТЗ: вторая воронка размещения статей «Болезни» (шаблон 31) **Проект:** arbat25.ru (MODX Revolution) **Раздел:** «Мы лечим» → `/myi-lechim/` **Версия:** 1.1 **Дата:** 2026-06-09 --- ## 1. Цель и контекст ### 1.1. Задача Организовать **массовое размещение SEO-статей о болезнях** по единому шаблону с: - структурированными секциями (симптомы, причины, лечение, FAQ и т.д.); - привязкой к **МКБ-10**; - блоком **клинических рекомендаций (КР)**; - **Schema.org** (MedicalWebPage / Disease); - рецензентом (E-E-A-T); - контролируемой публикацией (черновик → ревью → live). ### 1.2. Две воронки контента | | **Воронка 1 (legacy)** | **Воронка 2 (целевая)** | |--|------------------------|-------------------------| | Шаблоны MODX | 21 «Мы лечим», 24 (основной SEO) | **31 «Болезни»** (`tpl.disease`) | | Контент | Свободный HTML в поле `content` | TV `tv_disease_*` + опционально `content` | | URL | SEO-slug без МКБ | `{slug}-{icd10}` | | Создание | Ручной ввод в админке | **CLI-импорт** из JSONL / Word | | Публикация | Сразу `published=1` | По умолчанию **`published=0`** | | Schema | `schemaClinicalCitations` | `schemaDisease` (полный @graph) | | Ориентир | Обзорные коммерческие статьи | Нозологии по МКБ-10 | **Воронка 2 не заменяет воронку 1 автоматически.** На одну тему могут существовать параллельные URL (пример: `lechenie-depressii` — template 24, `lechenie-depressii-test` — template 31). Решение о миграции/каноникализации — отдельный этап. --- ## 2. Область применения ### 2.1. Входит в scope - Импорт статей из **Word (.docx)** и **JSONL** в template **31**. - Заполнение всех TV `tv_disease_*`. - Привязка к рубрикам раздела «Мы лечим» (`parent` ресурса). - Автоматическая и полуавтоматическая привязка **КР** (`tv_clinical_guidelines`). - Чек-лист ревью и публикации. - QA: вёрстка, TOC, CTA, JSON-LD, мобильная версия. ### 2.2. Не входит в scope (отдельные задачи) - Массовая миграция legacy-статей (21/24) на template 31. - Редизайн sidebar / меню раздела. - Генерация hero-изображений (если не переданы в импорте). - Редактура медицинских текстов (ответственность контент-команды). --- ## 3. Техническая архитектура ### 3.1. Ключевые сущности MODX | Сущность | ID / имя | Файл (source of truth) | |----------|----------|-------------------------| | Шаблон | **31** «Болезни» | `core/elements/templates/disease.tpl` | | Сниппет секций | `diseaseSection` | `core/elements/snippets/diseaseSection.php` | | Schema | `schemaDisease` | `core/elements/snippets/schemaDisease.php` | | КР-блок | `clinicalGuidelines` | `core/elements/snippets/clinicalGuidelines.php` | | Sidebar | `left-section-cures` | chunk + `leftCuresCustom.php` | | CTA запись | ресурс **126** | ссылка из hero и inline CTA | ### 3.2. Чанки секций (template 31) ``` core/elements/chunks/disease/ section.symptoms.tpl section.causes.tpl section.types.tpl section.treatments.tpl section.doctors.tpl section.faq.tpl section.reviewer.tpl ``` ### 3.3. Статические ресурсы | Файл | Назначение | |------|------------| | `assets/main/css/disease.css` | Стили страницы болезни | | `assets/main/css/clinical-guidelines.css` | Блок КР | | `assets/main/js/disease-toc.js` | Оглавление по секциям | | `assets/main/js/disease-cta-inject.js` | Inline CTA между секциями | ### 3.4. Инструменты импорта | Инструмент | Путь | |------------|------| | Импортёр | `tools/disease-import/import_diseases.php` | | Парсер Word | `tools/disease-import/convert_docx_batch.py` | | Пайплайн батча | `tools/disease-import/run_batch_pipeline.sh` | | JSON Schema | `tools/disease-import/disease-article.schema.json` | | Пример данных | `tools/disease-import/sample.diseases.jsonl` | | Документация | `tools/disease-import/README.md` | | КР-маппинг | `tools/cr-mapping/` | --- ## 4. URL и структура раздела ### 4.1. Базовый префикс ``` https://arbat25.ru/myi-lechim/{категория}/{alias-статьи} ``` ### 4.2. Рубрики (parent ID для импорта) | parent ID | Категория | URI-префикс | |-----------|-----------|-------------| | **191** | Психические расстройства | `myi-lechim/psixicheskie-rasstrojstva/` | | **199** | Психологические проблемы | `myi-lechim/psixologicheskie-problemyi/` | | **201** | Расстройства пищевого поведения | `myi-lechim/rasstrojstva-pishhevogo-povedeniya/` | | **205** | Лечение зависимостей | `myi-lechim/lechenie-zavisimostej/` | | **240** | Детско-подростковые направления | `myi-lechim/detskie-napravleniya/` | | **290** | Сексуальные расстройства | `myi-lechim/seksualnyie-rasstrojstva/` | | **405** | Гормональные расстройства | `myi-lechim/gormonalnyie-rasstrojstva/` | | **210** | Психиатрическое освидетельствование | `myi-lechim/psixiatricheskoe-osvidetelstvovanie/` | > **Дефолт импорта сейчас:** `parent=191`. Для других рубрик — явно указывать `meta.parent` в JSONL или флаг `--parent` при конвертации docx. ### 4.3. Правила alias (воронка 2) ``` {транслит-названия}-{код-мкб10-в-slug} ``` Код МКБ в slug: точка → дефис (`F84.0` → `f84-0`). **Не** добавлять слово `mkb` в alias. Примеры: - `delirij-ne-na-fone-demenczii-f05-0` - `detskij-autizm-f84-0` - `narushenie-aktivnosti-i-vnimaniya-sdvg-f90-0` ### 4.4. Правила заголовков | Поле MODX | Формат | |-----------|--------| | `pagetitle` | Краткое название болезни (H1) | | `longtitle` | `Лечение: {название} (МКБ-10 {код})` | | `description` | Meta description, до ~160 символов | --- ## 5. Контракт данных (JSONL) Каждая строка JSONL — одна статья. Схема: `tools/disease-import/disease-article.schema.json`. ### 5.1. Обязательные блоки ```json { "meta": { "pagetitle": "..." }, "disease": { "name": "...", "icd10": "F32" }, "sections": { "symptoms": [], "causes": [], "treatments": [] } } ``` ### 5.2. Маппинг полей → MODX #### Ресурс (стандартные поля) | JSON | Поле MODX | По умолчанию | |------|-----------|--------------| | `meta.pagetitle` | `pagetitle` | — | | `meta.longtitle` | `longtitle` | генерируется | | `meta.description` | `description` | — | | `meta.alias` | `alias` | slug + МКБ | | `meta.parent` | `parent` | **191** | | `meta.published` | `published` | **0** | | `meta.hidemenu` | `hidemenu` | **1** | | `extra_html` | `content` | пусто | #### Template Variables (`tv_disease_*`) | JSON | TV | Формат хранения | |------|-----|-----------------| | `disease.name` | `tv_disease_name` | string | | `disease.alt_names[]` | `tv_disease_alt_names` | строки через `\n` | | `disease.icd10` | `tv_disease_icd10` | string | | `disease.specialty` | `tv_disease_specialty` | default `Psychiatric` | | `disease.intro_html` | `tv_disease_intro` | HTML | | `disease.hero_image` | `tv_disease_hero_image` | URL/path | | `sections.symptoms[]` | `tv_disease_symptoms` | строки через `\n` | | `sections.causes[]` | `tv_disease_causes` | строки через `\n` | | `sections.types[]` | `tv_disease_types_json` | JSON `[{name,alt,icd,desc}]` | | `sections.treatments[]` | `tv_disease_treatments_json` | JSON `[{name,type,desc}]` | | `sections.faq[]` | `tv_disease_faq_json` | JSON `[{q,a}]` | | `review.reviewer_id` | `tv_disease_reviewer_id` | int, default **131** | | `review.last_reviewed` | `tv_disease_last_reviewed` | date | | `review.date_published` | `tv_disease_date_published` | date | | `review.date_modified` | `tv_disease_date_modified` | date | | `breadcrumbs_override[]` | `tv_disease_breadcrumbs_override` | JSON | | `doctors.specialties[]` | `tv_disease_doctor_specialties` | через `\|\|` | #### Клинические рекомендации (общий TV) | JSON / пайплайн | TV | |-----------------|-----| | CR auto-mapping | `tv_clinical_guidelines` (JSON `[{id,rev,title,url}]`) | | Отключить блок | `tv_cr_block_disabled` = `1` | ### 5.3. Типы лечения (`sections.treatments[].type`) Допустимые значения enum: - `MedicalTherapy` - `PsychologicalTreatment` - `TherapeuticProcedure` - `MedicalProcedure` --- ## 6. Структура страницы (template 31) Порядок блоков на фронте (`disease.tpl`): 1. **Hero** — H1, лид (`tv_disease_intro`), hero-image, CTA «Записаться на приём» → `[[~126]]` 2. **TOC** — автогенерация из видимых секций (`disease-toc.js`) 3. **Доп. текст** — `content` / `extra_html` (если есть) 4. **Симптомы** — `diseaseSection? &kind=symptoms` 5. **Причины** — `diseaseSection? &kind=causes` 6. **Виды / подтипы** — `diseaseSection? &kind=types` 7. **Лечение** — `diseaseSection? &kind=treatments` 8. **Врачи** — `diseaseSection? &kind=doctors` (3 случайных, template 22) 9. **Клинические рекомендации** — `[[!clinicalGuidelines]]` 10. **FAQ** — `diseaseSection? &kind=faq` 11. **Рецензент** — `diseaseSection? &kind=reviewer` 12. **Inline CTA** — вставка через `disease-cta-inject.js` 13. **Sidebar** — `left-section-cures` (sibling-статьи рубрики) 14. **Schema** — `[[schemaDisease]]` в `` --- ## 7. Процесс размещения (воронка 2) ### Этап 0. Подготовка контента **Вход:** пакет `.docx` (30–50 файлов на батч) или zip-архив (распаковать в inbox). **Два поддерживаемых формата Word:** | Формат | Когда используется | Именование файла | |--------|-------------------|------------------| | **Классический** | Стандартные SEO-статьи | `лечение _{Название}_ МКБ Fxx.x.docx` | | **Редакторский (Q&A)** | Статьи с заголовками-вопросами (H2/H3) | `{Название}_ МКБ Fxx.x.docx` | **Классический формат** — заголовки секций: **Симптомы**, **Причины**, **Лечение**, **МКБ-10**, **Частые вопросы** (и при необходимости: Виды, Подтипы). **Редакторский формат (Q&A):** - **Heading 2** — тематические блоки («Как проявляется…», «Почему возникает…», «Как лечат…»). - **Heading 3** — вопросы с ответами в абзацах ниже; все Q&A попадают в FAQ. - МКБ-10 **обязательно в имени файла** (парсер берёт код оттуда, а не из текста). - `pagetitle` / H1 = название болезни из имени файла (не первый вопрос в документе). Общие требования: - Один файл = одна нозология. - МКБ-10 в имени файла: `Fxx.x` или `Fxx`. **Выход:** папка `tools/disease-import/inbox/{batch-name}/*.docx` **Пример (батч june26 — детская психиатрия):** ```bash # Распаковка архива python3 -c "import zipfile; zipfile.ZipFile('uplstst/june26.zip').extractall('tools/disease-import/inbox/june26')" # parent=240 — «Детско-подростковые направления» ``` --- ### Этап 1. Конвертация docx → JSONL ```bash python3 tools/disease-import/convert_docx_batch.py \ --input-dir=tools/disease-import/inbox/batch-01 \ --out=tools/disease-import/data/batches/batch-01.jsonl \ --report=tools/disease-import/data/batches/batch-01-parse-report.csv \ --parent=191 \ --published=0 ``` **Критерии приёмки этапа:** - [ ] CSV-отчёт: `error=0`, желательно `warn=0` (для Q&A-формата парсер `docx_parser.py` классифицирует H2/H3 автоматически) - [ ] Все записи проходят `disease-article.schema.json` - [ ] У каждой записи заполнены: `pagetitle` (название болезни), `icd10`, `symptoms`, `causes`, `treatments`, `faq` (≥ 3) - [ ] `alias` = `{slug-названия}-{код-мкб}` (пример: `detskij-autizm-f84-0`, **без** `-mkb-` в середине) - [ ] `alias` уникален в батче и не конфликтует с существующими URI **Выбор `parent` по тематике батча:** | Батч / тема | `--parent` | |-------------|------------| | Психические расстройства (дефолт) | 191 | | Детско-подростковые (june26, F80–F98) | **240** | | Психологические проблемы | 199 | | Зависимости | 205 | | Сексуальные | 290 | | Гормональные | 405 | --- ### Этап 2. Dry-run импорта в MODX ```bash export DB_PASS='YOUR_PASS' BATCH=batch-01 APPLY=0 bash tools/disease-import/run_batch_pipeline.sh ``` или точечно: ```bash php tools/disease-import/import_diseases.php \ --input=tools/disease-import/data/batches/batch-01.jsonl \ --dry-run=1 ``` **Критерии приёмки:** - [ ] Отчёт импорта: 0 ошибок - [ ] Все ресурсы созданы с `template=31`, `published=0` - [ ] TV заполнены согласно маппингу (§5.2) --- ### Этап 3. Apply импорта + авто-КР ```bash BATCH=batch-01 APPLY=1 bash tools/disease-import/run_batch_pipeline.sh ``` Пайплайн автоматически: 1. Пишет ресурсы и TV в БД. 2. Выгружает inventory (`tools/cr-mapping/extract_inventory.sql`). 3. Строит proposals (`build_proposals.py`). 4. Применяет только `status=auto` (`filter_proposals_by_ids.py --confirm-auto-only`). 5. Записывает `tv_clinical_guidelines` (`apply_cr_mapping.php --apply`). **Для статей со статусом КР `weak` / `none`:** ручной или LLM-ревью по `tools/cr-mapping/DEEPSEEK-CR-MATCH-PROMPT.md`. --- ### Этап 4. Контент-ревью (чек-лист) Для каждой статьи в батче (в админке или на staging/preview): | # | Проверка | |---|----------| | 1 | H1 и лид соответствуют болезни, без «воды» | | 2 | МКБ-10 в `tv_disease_icd10` совпадает с клиническим смыслом | | 3 | Секции симптомов/причин/лечения не пустые | | 4 | FAQ — минимум 3 вопроса, ответы по делу | | 5 | Рецензент указан (`tv_disease_reviewer_id`, default 131) | | 6 | Блок КР отображается / корректно скрыт (`tv_cr_block_disabled`) | | 7 | TOC строится, якоря работают | | 8 | CTA «Записаться» ведёт на форму записи | | 9 | JSON-LD валиден ([Google Rich Results Test](https://search.google.com/test/rich-results)) | | 10 | Мобильная вёрстка без горизонтального скролла | | 11 | Нет дубля с опубликованной статьёй template 24 на ту же тему (или принято решение о каноникализации) | --- ### Этап 5. Публикация **Вариант A** — через re-import: ```json "meta": { "published": 1 } ``` **Вариант B** — SQL после ревью: ```sql UPDATE core_site_content SET published = 1, publishedon = UNIX_TIMESTAMP() WHERE id IN (...); ``` **После публикации:** - [ ] Очистить кеш MODX: `core/cache/*` - [ ] Синхронизировать live (`web2`) при необходимости - [ ] Проверить URL в sitemap / индексации - [ ] Зафиксировать в `tools/disease-import/data/published_articles_*.tsv` --- ## 8. Роли и ответственность | Роль | Задачи | |------|--------| | **Контент-редактор** | Подготовка docx, ревью текстов, FAQ | | **SEO-специалист** | alias, longtitle, description, каноникализация с template 24 | | **Мед. рецензент** | Проверка фактов, даты ревью, КР | | **Разработчик** | Импорт, фиксы парсера, шаблон, schema | | **DevOps** | Docker/DB, деплой на web2, cron | --- ## 9. Критерии готовности воронки (Definition of Done) Воронка 2 считается **рабочей для батча N**, если: 1. Импортировано **N** статей в template 31 без ошибок. 2. ≥ **90%** статей получили КР (`status=auto` или ручное подтверждение). 3. ≥ **95%** статей прошли чек-лист §7 этап 4. 4. Опубликовано **M** статей (`published=1`) после ревью. 5. Нет критических ошибок в Search Console / Rich Results по опубликованным URL. 6. Документирован батч: имя, дата, parent, список ID ресурсов. --- ## 10. Риски и ограничения | Риск | Митигация | |------|-----------| | Дубли URL с template 24 | Инвентаризация `tools/cr-mapping/data/inventory.tsv`, решение по каждой паре | | Парсер Word не распознал секцию | CSV-отчёт; для Q&A-формата — проверить H2-темы; ручная правка JSONL | | Q&A docx: H1 = вопрос вместо названия | МКБ и название **только из имени файла** `{Название}_ МКБ Fxx.x.docx` | | Слот врачей пустой | Проверить `tv_disease_doctor_specialties` | | КР не найдена автоматически | LLM-ревью / ручная привязка | | Публикация до ревью | Дефолт `published=0`, публикация только по чек-листу | | Конфликт alias | Upsert по alias в `import_diseases.php` — проверять перед apply | --- ## 11. Команды (шпаргалка) ```bash # 0. Распаковка zip → inbox (если нужно) python3 -c "import zipfile; zipfile.ZipFile('uplstst/BATCH.zip').extractall('tools/disease-import/inbox/BATCH')" # 1. Конвертация (пример: june26, детские направления) python3 tools/disease-import/convert_docx_batch.py \ --input-dir=tools/disease-import/inbox/june26 \ --out=tools/disease-import/data/batches/june26.jsonl \ --report=tools/disease-import/data/batches/june26-parse-report.csv \ --parent=240 --published=0 # 2. Dry-run (без Docker — напрямую на сервере) php tools/disease-import/import_diseases.php \ --input=tools/disease-import/data/batches/june26.jsonl \ --db-host=127.0.0.1 --db-name=arbat25_db --db-user=arbat25_user \ --db-pass=YOUR_PASS --dry-run=1 --default-parent=240 \ --report=tools/disease-import/data/batches/june26-dryrun.json # 3. Apply import php tools/disease-import/import_diseases.php \ --input=tools/disease-import/data/batches/june26.jsonl \ --db-host=127.0.0.1 --db-name=arbat25_db --db-user=arbat25_user \ --db-pass=YOUR_PASS --dry-run=0 --default-parent=240 \ --report=tools/disease-import/data/batches/june26-import.json # 4. CR mapping (после apply) mysql -u arbat25_user -p'YOUR_PASS' arbat25_db -B < tools/cr-mapping/extract_inventory.sql > tools/cr-mapping/data/inventory.tsv python3 tools/cr-mapping/build_proposals.py \ --inventory=tools/cr-mapping/data/inventory.tsv \ --catalog=tools/cr-mapping/cr_catalog.json \ --out-jsonl=tools/cr-mapping/data/proposals.june26.jsonl \ --out-csv=tools/cr-mapping/data/curation-june26.csv python3 tools/cr-mapping/filter_proposals_by_ids.py \ --proposals=tools/cr-mapping/data/proposals.june26.jsonl \ --import-report=tools/disease-import/data/batches/june26-import.json \ --out=tools/cr-mapping/data/proposals.june26.filtered.jsonl --confirm-auto-only php tools/cr-mapping/apply_cr_mapping.php \ --proposals=tools/cr-mapping/data/proposals.june26.filtered.jsonl \ --catalog=tools/cr-mapping/cr_catalog.json \ --db-host=127.0.0.1 --db-name=arbat25_db --db-user=arbat25_user --db-pass=YOUR_PASS \ --report=tools/cr-mapping/data/cr_apply_june26.csv --apply # Альтернатива: полный пайплайн через Docker (если php8a/mariadb доступны) export DB_PASS='YOUR_PASS' BATCH=june26 PARENT=240 APPLY=1 bash tools/disease-import/run_batch_pipeline.sh # 5. Список статей с КР python3 tools/disease-import/export_disease_cr_list.py \ --db-pass=YOUR_PASS \ --out=tools/disease-import/data/disease_articles_with_cr.tsv # 6. Очистка кеша rm -rf core/cache/* ``` > **Re-import / исправление alias:** upsert идёт по `alias + parent`. Если alias изменился после правки парсера — удалите старые ресурсы батча и импортируйте заново, либо задайте старый alias в JSONL вручную. --- ## 12. Ссылки на артефакты проекта | Артефакт | Путь | |----------|------| | Шаблон страницы | `core/elements/templates/disease.tpl` | | JSON Schema | `tools/disease-import/disease-article.schema.json` | | README импорта | `tools/disease-import/README.md` | | README КР | `tools/cr-mapping/README.md` | | Inventory статей | `tools/cr-mapping/data/inventory.tsv` | | Пример JSONL | `tools/disease-import/sample.diseases.jsonl` | | Inbox docx | `tools/disease-import/inbox/` | --- ## 13. Пример записи JSONL (минимальный) ```json { "meta": { "pagetitle": "Делирий, не на фоне деменции", "longtitle": "Лечение: Делирий, не на фоне деменции (МКБ-10 F05.0)", "description": "Симптомы, причины и лечение делирия (F05.0) в Московском психоэндокринологическом центре.", "alias": "delirij-ne-na-fone-demenczii-f05-0", "parent": 191, "published": 0, "hidemenu": 1 }, "disease": { "name": "Делирий, не на фоне деменции", "icd10": "F05.0", "specialty": "Psychiatric", "intro_html": "Краткий лид о болезни...
" }, "sections": { "symptoms": ["Нарушение сознания", "Дезориентация"], "causes": ["Инфекция", "Интоксикация"], "treatments": [ {"name": "Медикаментозная терапия", "type": "MedicalTherapy", "desc": "..."} ], "faq": [ {"q": "Когда обращаться к врачу?", "a": "..."} ] }, "review": { "reviewer_id": 131, "last_reviewed": "2026-05-28", "date_published": "2026-05-28", "date_modified": "2026-05-28" } } ``` --- ## 15. Батч june26 (справочник) | Параметр | Значение | |----------|----------| | Архив | `uplstst/june26.zip` | | Inbox | `tools/disease-import/inbox/june26/` | | Статей | 50 | | parent | **240** (`myi-lechim/detskie-napravleniya/`) | | Формат docx | Редакторский Q&A (Heading 2/3) | | Resource IDs | **1581–1630** (2026-06-09) | | Статус | `published=0` (черновики, ждут ревью) | | Inventory | `tools/disease-import/data/published_articles_june26.tsv` | **Проверка после импорта:** ```bash # Все 50 на месте, template 31, parent 240 mysql -u arbat25_user -p'YOUR_PASS' arbat25_db -e \ "SELECT COUNT(*) FROM core_site_content WHERE id BETWEEN 1581 AND 1630 AND template=31 AND parent=240" # Пример URL (после published=1) # https://arbat25.ru/myi-lechim/detskie-napravleniya/detskij-autizm-f84-0 ``` **КР:** для детских кодов F80–F98 авто-матчинг слабый (~1–2 из 50). Остальное — LLM-ревью по `tools/cr-mapping/DEEPSEEK-CR-MATCH-PROMPT.md` или ручная привязка; для части статей допустимо `tv_cr_block_disabled=1`. --- ## 14. История изменений | Версия | Дата | Изменения | |--------|------|-----------| | 1.0 | 2026-05-28 | Первая версия ТЗ воронки 2 | | 1.1 | 2026-06-09 | Формат Q&A docx; батч june26 (parent=240); команды без Docker; правила alias и re-import | --- ## README: импорт статей в шаблон «Болезни» Источник: `tools/disease-import/README.md` # Массовый импорт статей в шаблон `Болезни` Инструмент загружает статьи из JSONL/JSON в MODX (`template=31`) и заполняет `tv_disease_*` для нового шаблона. ## Файлы - `import_diseases.php` — CLI-импортёр (upsert resource + upsert TV). - `convert_docx_batch.py` + `docx_parser.py` — конвертация `.docx` → JSONL (stdlib, без python-docx). - `run_batch_pipeline.sh` — полный цикл батча: docx → JSONL → import → CR. - `make_sample_docx.py` — тестовые docx для проверки пайплайна без ваших файлов. - `export_disease_cr_list.py` — выгрузка статей template 31 и статуса блока КР. - `disease-article.schema.json` — целевой контракт входной записи. - `sample.diseases.jsonl` — пример формата. - `inbox/` — сюда кладёте `.docx` батчами (`pilot/`, `batch-01/`, …). ## Импорт из Word (батчи 30–50) ### Форматы docx 1. **Классический** — секции «Симптомы», «Причины», «Лечение», «МКБ-10», «Частые вопросы». 2. **Редакторский Q&A** — Heading 2 = тема, Heading 3 = вопрос + абзацы-ответы. Имя файла: `{Название болезни}_ МКБ Fxx.x.docx` или `лечение _{Название}_ МКБ Fxx.x.docx`. Парсер: `docx_parser.py` (`_parse_editorial_batch` для Q&A). ### 1. Положить docx ```text tools/disease-import/inbox/batch-01/*.docx ``` Рекомендуемые заголовки в Word: **Симптомы**, **Причины**, **Лечение**, **МКБ-10**, **Частые вопросы**. ### 2. Конвертация ```bash python3 tools/disease-import/convert_docx_batch.py \ --input-dir=tools/disease-import/inbox/batch-01 \ --out=tools/disease-import/data/batches/batch-01.jsonl \ --report=tools/disease-import/data/batches/batch-01-parse-report.csv \ --parent=191 --published=0 ``` Проверьте CSV-отчёт: строки `warn` / `error` — перед импортом. ### 3. Полный пайплайн (dry-run → apply) ```bash export DB_PASS='YOUR_PASS' # dry-run (только проверка import) BATCH=batch-01 APPLY=0 bash tools/disease-import/run_batch_pipeline.sh # запись в БД + авто-КР для status=auto BATCH=batch-01 APPLY=1 bash tools/disease-import/run_batch_pipeline.sh ``` Дефолты: `parent=191`, `published=0` (черновики), рецензент `131`. **Docker:** файлы синхронизируются в `/home/admin/web2/...`; в контейнере путь `/home/admin/web/arbat25.ru/public_html/...`. ### 4. Клинические рекомендации Пайплайн автоматически: 1. выгружает inventory (`tools/cr-mapping/extract_inventory.sql`); 2. строит proposals (`build_proposals.py`); 3. подтверждает только `status=auto` (`filter_proposals_by_ids.py --confirm-auto-only`); 4. пишет `tv_clinical_guidelines` (`apply_cr_mapping.php --apply`). Для `weak` / `none` — LLM-ревью как в [`../cr-mapping/DEEPSEEK-CR-MATCH-PROMPT.md`](../cr-mapping/DEEPSEEK-CR-MATCH-PROMPT.md). ### 5. Список статей с блоком КР ```bash python3 tools/disease-import/export_disease_cr_list.py \ --db-pass=YOUR_PASS \ --out=tools/disease-import/data/disease_articles_with_cr.tsv ``` ### 6. Публикация После ревью: в JSONL `"published": 1` и re-import, или SQL: ```sql UPDATE core_site_content SET published=1, publishedon=UNIX_TIMESTAMP() WHERE id IN (...); ``` ## Что ожидает сайт (map в TV) - `meta.pagetitle` -> `core_site_content.pagetitle` (обязательно) - `meta.longtitle` -> `core_site_content.longtitle` - `meta.description` -> `core_site_content.description` - `meta.alias` -> `core_site_content.alias` (если пусто, генерируется slug) - `meta.parent` -> `core_site_content.parent` (иначе `--default-parent`) - `meta.published` -> `core_site_content.published` - `meta.hidemenu` -> `core_site_content.hidemenu` - `meta.context_key` -> `core_site_content.context_key` - `extra_html` -> `core_site_content.content` - `disease.name` -> `tv_disease_name` - `disease.alt_names[]` -> `tv_disease_alt_names` (строки через `\n`) - `disease.icd10` -> `tv_disease_icd10` - `disease.specialty` -> `tv_disease_specialty` - `disease.intro_html` -> `tv_disease_intro` - `disease.hero_image` -> `tv_disease_hero_image` - `sections.symptoms[]` -> `tv_disease_symptoms` (строки через `\n`) - `sections.causes[]` -> `tv_disease_causes` (строки через `\n`) - `sections.types[]` -> `tv_disease_types_json` (JSON массив `{name,alt,icd,desc}`) - `sections.treatments[]` -> `tv_disease_treatments_json` (JSON массив `{name,type,desc}`) - `sections.faq[]` -> `tv_disease_faq_json` (JSON массив `{q,a}`) - `review.reviewer_id` -> `tv_disease_reviewer_id` (если 0/пусто, на рендере берётся дефолт 131) - `review.last_reviewed` -> `tv_disease_last_reviewed` - `review.date_published` -> `tv_disease_date_published` - `review.date_modified` -> `tv_disease_date_modified` - `breadcrumbs_override[]` -> `tv_disease_breadcrumbs_override` (JSON массив `{name,item}`) - `doctors.specialties[]` -> `tv_disease_doctor_specialties` (строка через `||`) ## Быстрый старт ```bash php tools/disease-import/import_diseases.php \ --input=tools/disease-import/sample.diseases.jsonl \ --db-host=127.0.0.1 \ --db-port=3306 \ --db-name=arbat25_db \ --db-user=arbat25 \ --db-pass=YOUR_PASS \ --dry-run=1 \ --batch-size=10 \ --limit=20 \ --report=/tmp/modx_inspect/disease_import_dryrun_report.json ``` ## Прод-импорт (пакетами) 1. Dry-run на первых 10-20 строках. 2. Импорт пакетами (`--batch-size=25` или `50`). 3. На каждый запуск писать `--report`. Пример: ```bash php tools/disease-import/import_diseases.php \ --input=/path/to/diseases-500.jsonl \ --db-host=127.0.0.1 --db-port=3306 \ --db-name=arbat25_db --db-user=arbat25 --db-pass=YOUR_PASS \ --dry-run=0 --batch-size=25 --offset=0 --limit=250 \ --rollback-batch-on-error=1 \ --report=/tmp/modx_inspect/import_batch_01.json ``` Далее второй запуск: ```bash php tools/disease-import/import_diseases.php \ --input=/path/to/diseases-500.jsonl \ --db-host=127.0.0.1 --db-port=3306 \ --db-name=arbat25_db --db-user=arbat25 --db-pass=YOUR_PASS \ --dry-run=0 --batch-size=25 --offset=250 --limit=250 \ --rollback-batch-on-error=1 \ --report=/tmp/modx_inspect/import_batch_02.json ``` ## Важные проверки после импорта - На странице есть секции `symptoms`, `types`, `treatments`, `doctors`, `reviewer`, `faq`. - Плашка `Рецензировано врачом` отображается. - В исходнике есть `