Initial commit: WordLoop 单词学习应用
Vue 前端 + FastAPI 后端,含部署脚本与词典数据。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
"""词典导入共享工具。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy.dialects.mysql import insert as mysql_insert
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from models import DictionaryEntry
|
||||
|
||||
_POS_PREFIX = re.compile(r"^[a-zA-Z]+\.\s*")
|
||||
_TAG_PREFIX = re.compile(r"^\[[^\]]+\]\s*")
|
||||
|
||||
|
||||
def clean_translation(text: str, max_len: int = 256) -> str:
|
||||
if not text:
|
||||
return ""
|
||||
lines = [ln.strip() for ln in text.replace("\r", "").split("\n") if ln.strip()]
|
||||
parts: list[str] = []
|
||||
for ln in lines:
|
||||
ln = _TAG_PREFIX.sub("", ln)
|
||||
ln = _POS_PREFIX.sub("", ln)
|
||||
if ln:
|
||||
parts.append(ln)
|
||||
result = ";".join(parts) if parts else text.strip()
|
||||
return result[:max_len]
|
||||
|
||||
|
||||
def normalize_row(raw: dict, source: Optional[str]) -> Optional[dict]:
|
||||
lemma_en = (raw.get("lemma_en") or raw.get("en") or raw.get("word") or "").strip().lower()
|
||||
zh = clean_translation(raw.get("zh") or raw.get("cn") or raw.get("translation") or "")
|
||||
if not lemma_en or not zh:
|
||||
return None
|
||||
if len(lemma_en) > 128:
|
||||
return None
|
||||
phonetic = (raw.get("phonetic") or "").strip() or None
|
||||
if phonetic and len(phonetic) > 128:
|
||||
phonetic = phonetic[:128]
|
||||
return {
|
||||
"lemma_en": lemma_en,
|
||||
"zh": zh,
|
||||
"phonetic": phonetic,
|
||||
"example_en": (raw.get("example_en") or "").strip() or None,
|
||||
"example_cn": (raw.get("example_cn") or "").strip() or None,
|
||||
"source": source or (raw.get("source") or "import"),
|
||||
}
|
||||
|
||||
|
||||
def upsert_batch(session: Session, rows: list[dict]) -> int:
|
||||
if not rows:
|
||||
return 0
|
||||
stmt = mysql_insert(DictionaryEntry).values(rows)
|
||||
stmt = stmt.on_duplicate_key_update(
|
||||
zh=stmt.inserted.zh,
|
||||
phonetic=stmt.inserted.phonetic,
|
||||
example_en=stmt.inserted.example_en,
|
||||
example_cn=stmt.inserted.example_cn,
|
||||
source=stmt.inserted.source,
|
||||
)
|
||||
session.execute(stmt)
|
||||
return len(rows)
|
||||
|
||||
|
||||
def upsert_entries(session: Session, raw_rows: list[dict], source: Optional[str], batch_size: int = 2000) -> int:
|
||||
batch: list[dict] = []
|
||||
total = 0
|
||||
for raw in raw_rows:
|
||||
row = normalize_row(raw, source)
|
||||
if not row:
|
||||
continue
|
||||
batch.append(row)
|
||||
if len(batch) >= batch_size:
|
||||
upsert_batch(session, batch)
|
||||
session.commit()
|
||||
total += len(batch)
|
||||
batch.clear()
|
||||
if batch:
|
||||
upsert_batch(session, batch)
|
||||
session.commit()
|
||||
total += len(batch)
|
||||
return total
|
||||
Reference in New Issue
Block a user