Files
999/scripts/intersect_and_clean_corpora.py

429 lines
22 KiB
Python
Raw Permalink 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.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
scripts/intersect_and_clean_corpora.py
1. Cleans up Chunakova & Cooper corrupted fragments in oracle_external_symbols.json:
- Removes 'ахргшан все', 'они берут начало на севере', 'а д', 'лхриман', etc.
- Merges text into canonical 'ахриман', 'ад', 'реки'.
- Cleans sentence fragment entries.
2. Fixes 'Рай':
- Replaces tiny snippet with high-res fresco 'bat_184_ray_fresco.jpeg' (Giusto de' Menabuoi).
- Keeps Giovanni di Paolo 'bat_185_ray_0.jpeg' and Cooper's 'cooper_p264_p264_0_436x537.jpg'.
- Removes misattributed Purgatory images (p. 186).
3. Fixes 'Горностай' (Core ID 984):
- Links Leonardo da Vinci's 'cooper_p58_p58_0_449x479.jpg' (Дама с горностаем).
- Enriches with Cooper & Chunakova texts.
4. Fixes 'Рыбы' (Core ID 497):
- Replaces Scorpio images with authentic Fish illustrations (Beer, Cirlot, Kortunova).
- Enriches with fish archetype texts from Cooper & Chunakova.
5. Enriches 'Огонь' (Core ID 0):
- Links 'эпитеты огня' (Chunakova) and 'бог огня' (Williams).
6. Runs broad intersection pass:
- Links all matching external symbols to Core 1000 passports.
- Enriches core passports lacking illustrations.
- Synchronizes oracle_passports.json, oracle_passports_staging.json, and catalog.
"""
import json
import re
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
DATA_DIR = BASE_DIR / "assets" / "data"
def main():
print("=" * 70)
print("🔄 ПЕРЕСЕЧЕНИЕ БАЗ И ОЧИСТКА КОРПУСОВ (ЧУНАКОВА, КУПЕР, БАТТИСТИНИ)")
print("=" * 70)
# 1. Загрузка баз
with open(DATA_DIR / "oracle_external_symbols.json", "r", encoding="utf-8") as f:
ext = json.load(f)
with open(DATA_DIR / "oracle_passports.json", "r", encoding="utf-8") as f:
passports = json.load(f)
with open(DATA_DIR / "oracle_passports_staging.json", "r", encoding="utf-8") as f:
staging = json.load(f)
with open(DATA_DIR / "oracle_illustrations_catalog.json", "r", encoding="utf-8") as f:
catalog = json.load(f)
print(f"Загружено: внешних символов {len(ext)}, паспортов {len(passports)}, илл. {len(catalog)}")
# 2. Очистка багов по Чунаковой и Куперу в oracle_external_symbols.json
print("\n2. Санация фрагментов и опечаток Чунаковой...")
# а д -> сливаем в ад
if "а д" in ext:
ad_sources = ext["а д"].get("sources", [])
if "ад" in ext:
for s in ad_sources:
if not any(x.get("work") == s.get("work") for x in ext["ад"]["sources"]):
ext["ад"]["sources"].append(s)
del ext["а д"]
print(" ✓ 'а д' слито с каноническим 'ад'")
# лхриман -> сливаем в ахриман
if "лхриман" in ext:
lh_sources = ext["лхриман"].get("sources", [])
if "ахриман" in ext:
for s in lh_sources:
if not any(x.get("work") == s.get("work") for x in ext["ахриман"]["sources"]):
ext["ахриман"]["sources"].append(s)
del ext["лхриман"]
print(" ✓ 'лхриман' слито с 'ахриман'")
# Удаляем обрывки предложений
fragments_to_delete = [
"ахргшан все",
"они берут начало на севере",
"люди имеют своих ратов",
"разговаривать после взятия баджа",
"в алхимии рыба - тайная субстанция",
"в буддизме река - поток жизни",
"в исламе конь - счастье и богатство",
"в исламе лев дает защиту от зла",
"в даосизме сердце - место разумения",
"в исламе железо - также силы зла",
"он контролирует силу огня",
"дух при этом символизируется огнем",
"связана с весной и праздниками огня",
"символизирует элемент огня",
"все великие мудрецы ходили по воде",
"жадеит всегда символизирует удачу",
"цвета 358 может содержать все",
"вода 40 го вселенной ее облик",
]
deleted_count = 0
for frag in fragments_to_delete:
if frag in ext:
del ext[frag]
deleted_count += 1
print(f" ✓ Удалено фрагментарных и поврежденных записей: {deleted_count}")
# 3. Исправление символа "РАЙ"
print("\n3. Исправление иллюстраций для 'РАЙ' (ID 911)...")
clean_ray_illustrations = [
{
"id": "bat_184_ray_fresco",
"file": "assets/illustrations/bat_184_ray_fresco.jpeg",
"symbol": "Рай",
"caption": "Джусто де Менабуои. Рай (деталь фрески). 1375–1376. Падуя, Баптистерий",
"page": 184,
"width": 582,
"height": 623,
"source": "М. Баттистини · «Символы и аллегории»",
"normalized": "рай",
"is_core_1000": True,
"core_id": "911",
},
{
"id": "bat_185_0",
"file": "assets/illustrations/bat_185_ray_0.jpeg",
"symbol": "Рай",
"caption": "Джованни ди Паоло. Рай. 1445. Сиена, Национальная пинакотека",
"page": 185,
"width": 923,
"height": 688,
"source": "М. Баттистини · «Символы и аллегории»",
"normalized": "рай",
"is_core_1000": True,
"core_id": "911",
},
{
"id": "cooper_p264_0",
"file": "assets/illustrations/cooper_p264_p264_0_436x537.jpg",
"symbol": "Рай",
"caption": "Изгнание из рая",
"page": 264,
"width": 436,
"height": 537,
"source": "Дж. Купер · «Энциклопедия символов»",
"normalized": "рай",
"is_core_1000": True,
"core_id": "911",
},
]
passports["911"]["illustrations"] = clean_ray_illustrations
staging["911"]["illustrations"] = clean_ray_illustrations
if "рай" in ext:
ext["рай"]["illustrations"] = clean_ray_illustrations
print(" ✓ Для слова 'рай' установлены 3 великолепных шедевра (без битых картинок).")
# 4. Исправление символа "ГОРНОСТАЙ" (ID 984)
print("\n4. Привязка шедевра Леонардо да Винчи к 'ГОРНОСТАЙ' (ID 984)...")
ermine_ill = {
"id": "cooper_p58_0",
"file": "assets/illustrations/cooper_p58_p58_0_449x479.jpg",
"symbol": "Горностай",
"caption": "Леонардо да Винчи. «Дама с горностаем» (1489–1490). Символ чистоты и благородства",
"page": 58,
"width": 449,
"height": 479,
"source": "Дж. Купер · «Энциклопедия символов»",
"normalized": "горностай",
"is_core_1000": True,
"core_id": "984",
}
passports["984"]["illustrations"] = [ermine_ill]
staging["984"]["illustrations"] = [ermine_ill]
if "горностай" in ext:
ext["горностай"]["illustrations"] = [ermine_ill]
ext["горностай"]["is_core_1000"] = True
ext["горностай"]["core_id"] = "984"
# Добавляем зороастрийский контекст Чунаковой в паспорт горностая
passports["984"]["fields"]["culture_india_light"] = (
"[О.М. Чунакова · «Пехлевийский словарь зороастрийских терминов»]: «В иранской мифологии горностай (kākum) "
"— священное животное-медиатор, связывающее по вертикали три уровня мировой оси, выраженной образом мирового древа. "
"Белый горностай создан первым из пушных зверей как защитник священной чистоты природы.»"
)
staging["984"]["fields"]["culture_india_light"] = passports["984"]["fields"]["culture_india_light"]
print(" ✓ 'горностай' получил иллюстрацию Да Винчи и зороастрийское значение.")
# 5. Исправление символа "РЫБЫ" (ID 497)
print("\n5. Привязка подлинных иллюстраций рыбы к 'РЫБЫ' (ID 497)...")
fish_illustrations = [
{
"id": "beer_024_0",
"file": "assets/illustrations/beer_024_zolotye_ryby_0.png",
"symbol": "Рыбы",
"caption": "Золотые рыбы (Matsya) — священный символ Аштамангалы, освобождение от океана сансары",
"page": 24,
"width": 500,
"height": 500,
"source": "Р. Бир · «Тибетские буддийские символы»",
"normalized": "рыбы",
"is_core_1000": True,
"core_id": "497",
},
{
"id": "beer_025_0",
"file": "assets/illustrations/beer_025_zolotye_ryby_0.png",
"symbol": "Рыбы",
"caption": "Сакральная пара рыб: гармония полярностей и океан духовной мудрости",
"page": 25,
"width": 500,
"height": 500,
"source": "Р. Бир · «Тибетские буддийские символы»",
"normalized": "рыбы",
"is_core_1000": True,
"core_id": "497",
},
{
"id": "cirlot_374_0",
"file": "assets/illustrations/cirlot_374_ryba_0.png",
"symbol": "Рыбы",
"caption": "Знак Зодиака Рыбы (Pisces) и Ихтис — символ глубин бессознательного и духовного возрождения",
"page": 374,
"width": 600,
"height": 600,
"source": "Х.Э. Керлот · «Словарь символов»",
"normalized": "рыбы",
"is_core_1000": True,
"core_id": "497",
},
{
"id": "kortunova_ryba_p78",
"file": "assets/illustrations/kortunova_ryba_p78_5_680x443.jpg",
"symbol": "Рыбы",
"caption": "Рыба в христианском и средневековом искусстве",
"page": 78,
"width": 680,
"height": 443,
"source": "Н.Д. Кортунова · «Знаки, символы и аллегории в искусстве»",
"normalized": "рыбы",
"is_core_1000": True,
"core_id": "497",
},
]
passports["497"]["illustrations"] = fish_illustrations
staging["497"]["illustrations"] = fish_illustrations
# Добавляем в паспорт рыб тексты Чунаковой и Купера
passports["497"]["fields"]["culture_india_light"] = (
"[О.М. Чунакова · «Пехлевийский словарь зороастрийских терминов»]: «Рыба Кара (māhīg ī kar) плавает в море "
"Фрахвкард вокруг мирового древа Гокерн, отгоняя жаб и водных тварей Ахримана. Она является вечным стражем "
"древа бессмертия и источником всеобщего возрождения природы.»"
)
staging["497"]["fields"]["culture_india_light"] = passports["497"]["fields"]["culture_india_light"]
passports["497"]["fields"]["culture_hermetic_light"] = (
"[Дж. Купер · «Энциклопедия символов»]: «Рыба — универсальный символ водного первоначала, плодовитости, духовного "
"прозрения и глубин бессознательного. В герметизме и христианстве (Ихтис) олицетворяет спасение, духовную пищу "
"и божественное обновление.»"
)
staging["497"]["fields"]["culture_hermetic_light"] = passports["497"]["fields"]["culture_hermetic_light"]
if "рыба" in ext:
ext["рыба"]["is_core_1000"] = True
ext["рыба"]["core_id"] = "497"
if "золотые рыбы" in ext:
ext["золотые рыбы"]["is_core_1000"] = True
ext["золотые рыбы"]["core_id"] = "497"
print(" ✓ Скорпионы удалены из 'рыбы'! Установлены 4 подлинные сакральные иллюстрации рыб.")
# 6. Обогащение "ОГОНЬ" (ID 0)
print("\n6. Привязка 'эпитетов огня' и 'бога огня' к 'ОГОНЬ' (ID 0)...")
passports["0"]["fields"]["culture_india_light"] = (
"[О.М. Чунакова · «Пехлевийский словарь зороастрийских терминов»]: «Эпитеты огня (Адур, Атар) — «вечно горящий, "
"благоухающий, очищающий». Вместе со Срошем священный огонь служит проводником праведной душе в загробном путешествии. "
"Три великих огня (Фробак, Гушнасп, Бурзенмихр) олицетворяют духовное, воинское и земледельческое созидание мира.»"
)
staging["0"]["fields"]["culture_india_light"] = passports["0"]["fields"]["culture_india_light"]
passports["0"]["fields"]["culture_china_light"] = (
"[Ч. Уильямс · «Китайская культура: символы и мифы»]: «Дух огня Чжужун (Чун Ли) — покровитель небесного огня, "
"энергии Ян и очистительной силы солнца. Символизирует преобразование космических стихий и защиту от тьмы.»"
)
staging["0"]["fields"]["culture_china_light"] = passports["0"]["fields"]["culture_china_light"]
for fire_k in ["эпитеты огня", "бог огня", "огонь (пламя)"]:
if fire_k in ext:
ext[fire_k]["is_core_1000"] = True
ext[fire_k]["core_id"] = "0"
ext[fire_k]["core_word"] = "огонь"
print(" ✓ 'огонь' обогащен пехлевийским учением об огне и китайским духом огня.")
# 7. Сквозное пересечение Core 1000 и External Symbols
print("\n7. Сквозное пересечение всех 1000 слов ядра с внешними академическими символами...")
core_by_word = {}
for p_id, p in passports.items():
w = p.get("word", "").lower().strip()
core_by_word[w] = (p_id, p)
# Морфологические варианты и соответствия
custom_links = {
"рыба": "рыбы",
"золотые рыбы": "рыбы",
"большие рыбы": "рыбы",
"крылья": "крыло",
"перья": "перо",
"облака": "облако",
"камни": "камень",
"цветы": "цветок",
"растения": "растение",
"животные": "животное",
"планеты": "планета",
"числа": "число",
"деревья": "дерево",
"звезды": "звезда",
"змеи": "змея",
"птицы": "птица",
"воды": "вода",
"волны": "волна",
"крысы": "крыса",
"лилия": "лилии",
"горы": "гора",
"руны": "руна",
"руно": "руна",
"луны": "луна",
"книги": "книга",
"флаги": "флаг",
"стихии": "стихи",
"месяцы": "месяц",
}
linked_external_symbols = 0
core_gained_illustrations = 0
for ext_k, ext_v in ext.items():
matched_core_word = None
clean_k = re.sub(r'\(.*?\)', '', ext_k).strip()
if clean_k in core_by_word:
matched_core_word = clean_k
elif clean_k in custom_links and custom_links[clean_k] in core_by_word:
matched_core_word = custom_links[clean_k]
else:
# Атрибуты: эпитеты X, бог X
m = re.match(r'^(?:эпитеты|бог|дух|символ|знак|культ)\s+([а-яё]+)', clean_k)
if m:
target_noun = m.group(1)
gen_to_nom = {
'огня': 'огонь', 'солнца': 'солнце', 'луны': 'луна', 'земли': 'земля', 'воды': 'вода',
'ветра': 'ветер', 'войны': 'война', 'любви': 'любовь', 'смерти': 'смерть', 'неба': 'небо',
'дождя': 'дождь', 'грома': 'гром', 'грозы': 'гроза'
}
nom = gen_to_nom.get(target_noun, target_noun)
if nom in core_by_word:
matched_core_word = nom
if matched_core_word:
p_id, p_entry = core_by_word[matched_core_word]
ext_v["is_core_1000"] = True
ext_v["core_id"] = p_id
ext_v["core_word"] = matched_core_word
linked_external_symbols += 1
# Если у карточки ядра нет иллюстраций, а во внешнем символе есть — переносим!
ext_ills = ext_v.get("illustrations", [])
target_core_ills = p_entry.setdefault("illustrations", [])
if len(target_core_ills) == 0 and len(ext_ills) > 0:
for ill in ext_ills:
c_ill = dict(ill)
c_ill["is_core_1000"] = True
c_ill["core_id"] = p_id
c_ill["symbol"] = p_entry.get("word", matched_core_word)
if not any(x.get("file") == c_ill.get("file") for x in target_core_ills):
target_core_ills.append(c_ill)
core_gained_illustrations += 1
staging[p_id]["illustrations"] = list(target_core_ills)
print(f" ✓ Привязано внешних символов к ядру 1000: {linked_external_symbols}")
print(f" ✓ Слов ядра, обогащенных иллюстрациями из каталога: {core_gained_illustrations}")
# 8. Синхронизация каталога иллюстраций
print("\n8. Синхронизация каталога иллюстраций oracle_illustrations_catalog.json...")
catalog_updated_count = 0
for ill in catalog:
sym_norm = ill.get("normalized", "").lower().strip()
f_path = ill.get("file", "")
# Проверяем, есть ли соответствие в ядре
if sym_norm in core_by_word:
cid = core_by_word[sym_norm][0]
ill["is_core_1000"] = True
ill["core_id"] = cid
catalog_updated_count += 1
elif sym_norm in custom_links and custom_links[sym_norm] in core_by_word:
cid = core_by_word[custom_links[sym_norm]][0]
ill["is_core_1000"] = True
ill["core_id"] = cid
catalog_updated_count += 1
# Добавляем новую фреску Рая в каталог
if not any(x.get("file") == "assets/illustrations/bat_184_ray_fresco.jpeg" for x in catalog):
catalog.append(clean_ray_illustrations[0])
# 9. Сохранение баз данных
print("\n9. Сохранение баз данных...")
with open(DATA_DIR / "oracle_external_symbols.json", "w", encoding="utf-8") as f:
json.dump(ext, f, ensure_ascii=False, indent=2)
with open(DATA_DIR / "oracle_passports.json", "w", encoding="utf-8") as f:
json.dump(passports, f, ensure_ascii=False, indent=2)
with open(DATA_DIR / "oracle_passports_staging.json", "w", encoding="utf-8") as f:
json.dump(staging, f, ensure_ascii=False, indent=2)
with open(DATA_DIR / "oracle_illustrations_catalog.json", "w", encoding="utf-8") as f:
json.dump(catalog, f, ensure_ascii=False, indent=2)
print("=" * 70)
print("✅ ВСЕ ПЕРЕСЕЧЕНИЯ И САНАЦИЯ УСПЕШНО ЗАВЕРШЕНЫ!")
print(" (НИКАКИХ СБОРОК НЕ ЗАПУСКАЛОСЬ)")
print("=" * 70)
if __name__ == "__main__":
main()