first commit
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
读取 db/menu_map.json, 构建功能树写入 SQLite(features 表)。
|
||||
层级: level0=顶层模块, level1=分组, level2=菜单页(叶子)
|
||||
并为每个叶子分配期望截图路径 screenshots/<序号_模块>/<分组>/<序号_名称>.jpg
|
||||
|
||||
menu_map.json 结构(由实时爬取生成):
|
||||
{
|
||||
"<模块名>": {
|
||||
"loc": "落地页URL",
|
||||
"desc": "模块释义(可选)",
|
||||
"understanding": "开发理解(可选)",
|
||||
"groups": [ {"title": "分组名", "items": [ {"name":"页名","href":"/路径","desc":"","understanding":""}, ...] } ],
|
||||
"single": {"name":"页名","href":"/路径"} # 无侧边栏的单页模块(可选)
|
||||
},
|
||||
...
|
||||
}
|
||||
"""
|
||||
import json, os, re, sqlite3
|
||||
|
||||
BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
MAP = os.path.join(BASE, "db", "menu_map.json")
|
||||
DB = os.path.join(BASE, "db", "research.db")
|
||||
ORIGIN = "https://s-demob.xinrenxinshi.show"
|
||||
|
||||
|
||||
def sanitize(s):
|
||||
s = re.sub(r'[\\/:*?"<>|]', "_", s or "").strip()
|
||||
return s[:40] or "page"
|
||||
|
||||
|
||||
def full_url(href):
|
||||
if not href:
|
||||
return ""
|
||||
if href.startswith("http"):
|
||||
return href
|
||||
return ORIGIN + (href if href.startswith("/") else "/" + href)
|
||||
|
||||
|
||||
def main():
|
||||
data = json.load(open(MAP, encoding="utf-8"))
|
||||
conn = sqlite3.connect(DB)
|
||||
conn.row_factory = sqlite3.Row
|
||||
cur = conn.cursor()
|
||||
cur.execute("DELETE FROM features")
|
||||
|
||||
def up(obj):
|
||||
keys = list(obj.keys()); cols = ",".join(keys); ph = ",".join(["?"] * len(keys))
|
||||
cur.execute(f"INSERT OR REPLACE INTO features ({cols}) VALUES ({ph})", [obj[k] for k in keys])
|
||||
|
||||
for mi, module in enumerate(data.keys(), 1):
|
||||
v = data[module]
|
||||
mod_key = f"mod::{module}"
|
||||
seq_mod = f"{mi:02d}_{sanitize(module)}"
|
||||
up(dict(node_key=mod_key, parent_key="", level=0, name=module,
|
||||
full_path=module, url=v.get("loc", ""),
|
||||
description=v.get("desc", f"{module}模块。"),
|
||||
understanding=v.get("understanding", ""), sort_order=mi, keep=1))
|
||||
|
||||
groups = v.get("groups", [])
|
||||
single = v.get("single")
|
||||
flat_items = v.get("items")
|
||||
# 扁平模式: 模块直接挂功能页(level2), 无中间分组层
|
||||
if not groups and flat_items:
|
||||
for ii, it in enumerate(flat_items, 1):
|
||||
nm = it["name"]; href = it.get("href", "")
|
||||
leaf_key = f"{module}::{href or nm}"
|
||||
rel = f"screenshots/{seq_mod}/{ii:02d}_{sanitize(nm)}.jpg"
|
||||
up(dict(node_key=leaf_key, parent_key=mod_key, level=2, name=nm,
|
||||
full_path=f"{module} / {nm}", url=full_url(href),
|
||||
description=it.get("desc", f"{module}模块下「{nm}」相关功能页。"),
|
||||
understanding=it.get("understanding", ""),
|
||||
screenshot_path=rel, sort_order=ii, keep=1))
|
||||
continue
|
||||
if not groups and single:
|
||||
nm = single["name"]; href = single.get("href", "")
|
||||
leaf_key = f"{module}::{href or nm}"
|
||||
rel = f"screenshots/{seq_mod}/{sanitize(nm)}.jpg"
|
||||
up(dict(node_key=leaf_key, parent_key=mod_key, level=2, name=nm,
|
||||
full_path=f"{module} / {nm}", url=full_url(href),
|
||||
description=single.get("desc", f"{module}模块下「{nm}」相关功能页。"),
|
||||
understanding=single.get("understanding", ""),
|
||||
screenshot_path=rel, sort_order=1, keep=1))
|
||||
continue
|
||||
|
||||
gi = 0
|
||||
for g in groups:
|
||||
gtitle = g.get("title") or "常规"
|
||||
gi += 1
|
||||
grp_key = f"{mod_key}::grp::{gi}_{gtitle}"
|
||||
up(dict(node_key=grp_key, parent_key=mod_key, level=1, name=gtitle,
|
||||
full_path=f"{module} / {gtitle}", url="",
|
||||
description=f"{module}模块下「{gtitle}」功能分组。",
|
||||
understanding="", sort_order=gi, keep=1))
|
||||
for ii, it in enumerate(g.get("items", []), 1):
|
||||
nm = it["name"]; href = it.get("href", "")
|
||||
leaf_key = f"{module}::{href or (gtitle + '/' + nm)}"
|
||||
rel = f"screenshots/{seq_mod}/{sanitize(gtitle)}/{ii:02d}_{sanitize(nm)}.jpg"
|
||||
up(dict(node_key=leaf_key, parent_key=grp_key, level=2, name=nm,
|
||||
full_path=f"{module} / {gtitle} / {nm}", url=full_url(href),
|
||||
description=it.get("desc", f"{module}模块下「{nm}」相关功能页。"),
|
||||
understanding=it.get("understanding", ""),
|
||||
screenshot_path=rel, sort_order=ii, keep=1))
|
||||
conn.commit()
|
||||
for lv in (0, 1, 2):
|
||||
n = cur.execute("SELECT COUNT(*) FROM features WHERE level=?", (lv,)).fetchone()[0]
|
||||
print(f"level{lv}: {n}")
|
||||
print("total:", cur.execute("SELECT COUNT(*) FROM features").fetchone()[0])
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user