feat: complete academic symbol lexicon heal, 2-column Cooper extraction, and updated assets
This commit is contained in:
@@ -0,0 +1,428 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user