dana-medical-site/migrations/import/export_doctor_bio.py
2026-10-14 13:33:13 +00:00

88 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
Заполняет doctor_bio_entries из свойств врача в дампе Bitrix, которые
export_seed.py по ошибке не читал: EDUCATION(331), AWARDS(330), CONFERENCES(332).
Значения хранятся либо простым текстом, либо сериализованным PHP-массивом вида
a:2:{s:4:"TEXT";s:N:"...";s:4:"TYPE";s:4:"HTML";} — сначала извлекаем текст,
затем режем на отдельные пункты (по <li> или по <br>/переводу строки),
из каждого пытаемся достать год.
"""
import sqlread, io, re, html
P = 'D:/medkor-local/tmp/dana/db.sql'
OUT = io.open('seed_doctor_bio.sql', 'w', encoding='utf-8')
def esc(s):
if s is None:
return "NULL"
return "'" + str(s).replace("\\", "\\\\").replace("'", "''") + "'"
def extract_text(raw):
"""Достаёт TEXT из сериализованного PHP-массива Bitrix, если он там есть."""
m = re.search(r's:4:"TEXT";s:\d+:"(.*)";s:4:"TYPE"', raw, re.S)
return m.group(1) if m else raw
def split_entries(raw):
text = extract_text(raw)
text = text.replace('\\r\\n', '\n').replace('rn', '\n') # артефакты дампа
# снимаем HTML-экранирование ДО поиска тегов — в паре карточек теги были
# вставлены как текст (&lt;ul&gt; вместо <ul>), и без этого шага <li>
# не находился, а обрывки "<ul>"/"</ul>" оседали как отдельные записи
text = html.unescape(text)
items = re.findall(r'(?is)<li[^>]*>(.*?)</li>', text)
if not items:
parts = re.split(r'(?i)<br\s*/?>|\n', text)
items = [p for p in parts if p.strip()]
out = []
for it in items:
t = html.unescape(re.sub(r'(?s)<[^>]+>', ' ', it)).strip()
t = re.sub(r'\s+', ' ', t)
# чистые обрывки разметки без текста (<ul>, </ul>, пустой <p></p> и т.п.)
if t and re.search(r'[А-Яа-яA-Za-z0-9]', t):
out.append(t)
return out
YEAR_RE = re.compile(r'(19|20)\d{2}')
def parse_year(text):
m = YEAR_RE.search(text)
return int(m.group(0)) if m else None
PROPS = {'331': 'education', '330': 'award', '332': 'conference'}
values = {} # (elem_id, prop_id) -> value
for r in sqlread.rows(P, 'b_iblock_element_property'):
if r.get('IBLOCK_PROPERTY_ID') in PROPS and r.get('VALUE'):
values[(r['IBLOCK_ELEMENT_ID'], r['IBLOCK_PROPERTY_ID'])] = r['VALUE']
doctors = [r for r in sqlread.rows(P, 'b_iblock_element')
if r['IBLOCK_ID'] == '29' and r.get('ACTIVE') == 'Y']
OUT.write('BEGIN;\n')
total = 0
per_doctor_any = 0
for d in doctors:
eid = d['ID']
had_any = False
for prop_id, kind in PROPS.items():
raw = values.get((eid, prop_id))
if not raw:
continue
entries = split_entries(raw)
for i, text in enumerate(entries):
year = parse_year(text)
title = text if len(text) <= 300 else text[:297] + '...'
OUT.write(
"INSERT INTO doctor_bio_entries (doctor_id, kind, year_from, title, sort) "
"SELECT id, %s, %s, %s, %s FROM doctors WHERE legacy_id=%s;\n" % (
esc(kind), year if year else 'NULL', esc(title), i + 1, eid))
total += 1
had_any = True
if had_any:
per_doctor_any += 1
OUT.write('COMMIT;\n')
OUT.close()
print('врачей с хотя бы одной записью:', per_doctor_any, 'из', len(doctors))
print('всего записей doctor_bio_entries:', total)