# -*- 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";} — сначала извлекаем текст,
затем режем на отдельные пункты (по
или по
/переводу строки),
из каждого пытаемся достать год.
"""
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-экранирование ДО поиска тегов — в паре карточек теги были
# вставлены как текст (<ul> вместо ), и без этого шага -
# не находился, а обрывки "" оседали как отдельные записи
text = html.unescape(text)
items = re.findall(r'(?is)
- ]*>(.*?)
', text)
if not items:
parts = re.split(r'(?i)
|\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)
# чистые обрывки разметки без текста (, пустой и т.п.)
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)