Skip to content

Instantly share code, notes, and snippets.

@xeioex
Created September 10, 2025 19:25
Show Gist options
  • Save xeioex/770315e4efc92688fa05b5482b33ddfa to your computer and use it in GitHub Desktop.
Save xeioex/770315e4efc92688fa05b5482b33ddfa to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Anki TXT Cards Creator
Создает объединенные файлы карточек в формате .txt для импорта в Anki
Поддерживает обработку множества JSON файлов через glob patterns
"""
import json
import os
import glob
from typing import List, Dict, Any, Tuple
import argparse
def load_json_data(file_path: str) -> List[Dict[str, Any]]:
"""Загружает данные из JSON файла"""
try:
with open(file_path, 'r', encoding='utf-8') as file:
data = json.load(file)
return data
except FileNotFoundError:
print(f"Ошибка: Файл {file_path} не найден")
return []
except json.JSONDecodeError as e:
print(f"Ошибка при парсинге JSON в файле {file_path}: {e}")
return []
def create_txt_file(data: List[Dict[str, Any]], output_file: str, delimiter: str = '\t'):
"""
Создает текстовый файл для импорта в Anki в стандартном формате
Формат: ID [TAB] "содержимое"
"""
try:
with open(output_file, 'w', encoding='utf-8', newline='') as file:
# Записываем заголовки в формате Anki
file.write("#separator:tab\n")
file.write("#html:true\n")
for i, item in enumerate(data):
term = item.get('term', '').strip()
definition = item.get('definition', '').strip()
# Очищаем определение от лишних пробелов и переносов
definition = ' '.join(definition.split())
# Экранируем кавычки в содержимом (двойные кавычки заменяем на "")
term_escaped = term.replace('"', '""')
definition_escaped = definition.replace('"', '""')
# Объединяем термин и определение
content = f"{term_escaped} {definition_escaped}"
# Записываем в формате Anki: ID[TAB]"содержимое"
file.write(f"{i}{delimiter}\"{content}\"\n")
print(f"✅ Создан текстовый файл: {output_file}")
print(f" Карточек: {len(data)}")
print(f" Формат: стандартный Anki с разделителем табуляция")
except Exception as e:
print(f"Ошибка при создании текстового файла: {e}")
def create_txt_file_two_fields(data: List[Dict[str, Any]], output_file: str, delimiter: str = '\t'):
"""
Создает текстовый файл с двумя отдельными полями для импорта в Anki
Формат: "термин" [TAB] "определение"
"""
try:
with open(output_file, 'w', encoding='utf-8', newline='') as file:
# Записываем заголовки в формате Anki
file.write("#separator:tab\n")
file.write("#html:true\n")
for item in data:
term = item.get('term', '').strip()
definition = item.get('definition', '').strip()
# Очищаем определение от лишних пробелов и переносов
definition = ' '.join(definition.split())
# Экранируем кавычки в содержимом (двойные кавычки заменяем на "")
term_escaped = term.replace('"', '""')
definition_escaped = definition.replace('"', '""')
# Записываем в формате: "Front"[TAB]"Back"
file.write(f'"{term_escaped}"{delimiter}"{definition_escaped}"\n')
print(f"✅ Создан текстовый файл с двумя полями: {output_file}")
print(f" Карточек: {len(data)}")
print(f" Формат: двухполевые карточки")
except Exception as e:
print(f"Ошибка при создании текстового файла: {e}")
def print_preview(data: List[Dict[str, Any]], count: int = 3):
"""Показывает preview первых карточек"""
print(f"\n📋 Превью первых {min(count, len(data))} карточек:")
print("-" * 50)
for i, item in enumerate(data[:count]):
term = item.get('term', 'N/A')
definition = item.get('definition', 'N/A')
definition_short = (definition[:100] + '...') if len(definition) > 100 else definition
print(f"{i+1}. {term}")
print(f" {definition_short}")
print()
def main():
parser = argparse.ArgumentParser(description='Создание TXT файлов карточек для Anki')
parser.add_argument('input_files', nargs='+', help='Путь(и) к JSON файлам (можно указать несколько файлов)')
parser.add_argument('-o', '--output', default='anki_cards.txt', help='Базовое имя выходного файла')
args = parser.parse_args()
# Загружаем данные из всех файлов
print(f"🔍 Обрабатываем файлы: {', '.join(args.input_files)}")
all_data = []
processed_files = []
for file_path in sorted(args.input_files):
if os.path.exists(file_path):
print(f"📂 Загружаем: {file_path}")
data = load_json_data(file_path)
if data:
all_data.extend(data)
processed_files.append(file_path)
print(f" ✅ Загружено {len(data)} карточек")
else:
print(f" ❌ Пустой файл или ошибка загрузки")
else:
print(f"⚠️ Файл не найден: {file_path}")
if not all_data:
print("❌ Нет данных для обработки")
return
print(f"\n📊 Итого:")
print(f" Обработано файлов: {len(processed_files)}")
print(f" Загружено карточек: {len(all_data)}")
if processed_files:
print(f" Файлы:")
for file_path in processed_files:
print(f" • {file_path}")
# Показываем превью
print_preview(all_data)
# Создаем файл
print(f"\n🔄 Создаем объединенный TXT файл...")
create_txt_file(all_data, args.output)
print(f"\n🎉 Готово! Файл можно импортировать в Anki.")
print(f"\n💡 Инструкция по импорту:")
print(f" 1. Откройте Anki")
print(f" 2. Файл → Импорт")
print(f" 3. Выберите файл: {args.output}")
print(f" 4. Настройки импорта определятся автоматически")
print(f" 5. Нажмите 'Импорт'")
if __name__ == "__main__":
# Если запускается без аргументов, используем примеры
import sys
if len(sys.argv) == 1:
# Тестовый режим
print("🧪 Тестовый режим с примером данных...")
# Создаем тестовые данные на основе предоставленного примера
test_data = [
{
"definition": "without any delay; immediately (без лишних слов)",
"term": "without further ado"
},
{
"definition": "(adj.) unusual and strange, sometimes in an unpleasant way (Своеобразный)",
"term": "peculiar"
},
{
"definition": "(adj.) not willing to do something and therefore slow to do it",
"term": "reluctant"
}
]
print_preview(test_data)
print("\n📝 Создаем примеры файлов:")
create_txt_file(test_data, "example_cards.txt")
print(f"\n💡 Примеры использования:")
print(f" # Один файл")
print(f' python3 json_to_anki_txt.py "input.json"')
print(f" ")
print(f" # Несколько файлов")
print(f' python3 json_to_anki_txt.py "file1.json" "file2.json" "file3.json"')
print(f" ")
print(f" # Файлы с пробелами в названии (bash развернет *)")
print(f' python3 json_to_anki_txt.py From\\ The\\ Boyz.\\ Part\\ *.json')
print(f" ")
print(f" # Все JSON файлы в папке")
print(f" python3 json_to_anki_txt.py *.json")
print(f" ")
print(f" # Пользовательское имя выходного файла")
print(f" python3 json_to_anki_txt.py *.json -o combined_vocabulary")
else:
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment