chore:更新文档资产
This commit is contained in:
+17
-20
@@ -1,4 +1,4 @@
|
||||
"""共享配置:dws 路径解析 + 群组定义"""
|
||||
"""共享配置:dws / lark-cli 路径解析 + 群组定义"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
@@ -8,11 +8,9 @@ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
PROJECT_ROOT = os.path.dirname(SCRIPT_DIR)
|
||||
TOOLS_DIR = os.path.join(PROJECT_ROOT, "tools")
|
||||
|
||||
# dws 路径查找优先级:
|
||||
# 1. 环境变量 DWS_PATH
|
||||
# 2. 项目 tools/ 目录(从 GitHub 下载的独立版本)
|
||||
# 3. 悟空内置路径(向后兼容)
|
||||
# 4. 系统 PATH
|
||||
# ──────────────────────────────────────────────
|
||||
# dws (钉钉工作空间 CLI)
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
_WUKONG_PATHS = [
|
||||
os.path.expanduser(r"~\.real\.bin\dws\bin\dws.exe"),
|
||||
@@ -21,40 +19,39 @@ _WUKONG_PATHS = [
|
||||
|
||||
|
||||
def _find_dws():
|
||||
# 1) 显式指定
|
||||
env = os.environ.get("DWS_PATH")
|
||||
if env and os.path.isfile(env):
|
||||
return env
|
||||
|
||||
# 2) 项目 tools/ 目录
|
||||
ext = ".exe" if platform.system() == "Windows" else ""
|
||||
local = os.path.join(TOOLS_DIR, "dws" + ext)
|
||||
if os.path.isfile(local):
|
||||
return local
|
||||
|
||||
# 3) 悟空内置(向后兼容)
|
||||
for p in _WUKONG_PATHS:
|
||||
if os.path.isfile(p):
|
||||
return p
|
||||
|
||||
# 4) 系统 PATH
|
||||
found = shutil.which("dws")
|
||||
if found:
|
||||
return found
|
||||
|
||||
raise FileNotFoundError(
|
||||
"找不到 dws CLI。请执行以下任一操作:\n"
|
||||
" 1) 运行: python scripts/setup_dws.py (从 GitHub 自动下载)\n"
|
||||
" 2) 手动下载: https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/latest\n"
|
||||
" 将 dws.exe 放到 tools/ 目录\n"
|
||||
" 3) 设置环境变量: DWS_PATH=<你的 dws 路径>"
|
||||
"找不到 dws CLI。请将 dws.exe 放到 tools/ 目录或设置 DWS_PATH 环境变量。"
|
||||
)
|
||||
|
||||
|
||||
DWS = _find_dws()
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# lark-cli (飞书文档 CLI)
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
LARK_CLI = os.path.join(TOOLS_DIR, "lark-cli", "lark-cli.exe")
|
||||
LARK_CONFIG_DIR = os.path.join(TOOLS_DIR, "lark-config")
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# 钉钉群组 ID
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
GROUPS = {
|
||||
"创新组": "cidMuM+itt5PeY7xNSWsv3M0g==",
|
||||
"dc战略问题研究院": "cidoUneRB4Db8TAXaTrKxkQAw==",
|
||||
"创新组": "cidMuM+itt5PeY7xNSWsv3M0g==",
|
||||
"天龙计划X小游戏矩阵": "cid/Vb3hSjdv4sIIs8Fp7sC4g==",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import json, re, os, glob
|
||||
|
||||
input_dir = r'D:\desktop\feishu_docs_summary\output\feishu-docs'
|
||||
output_dir = r'D:\desktop\feishu_docs_summary\output\feishu-docs\md'
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
def html_to_md(html):
|
||||
if not html:
|
||||
return ''
|
||||
text = html
|
||||
text = re.sub(r'<img[^>]*alt="([^"]*?)"[^>]*/>', r'[图片: \1]', text)
|
||||
text = re.sub(r'<img[^>]*/>', '[图片]', text)
|
||||
text = re.sub(r'<sheet[^>]*/>', '[表格]', text)
|
||||
text = re.sub(r'</?grid[^>]*>', '', text)
|
||||
text = re.sub(r'<column[^>]*>', '', text)
|
||||
text = re.sub(r'</column>', '', text)
|
||||
text = re.sub(r'<latex[^>]*>(.*?)</latex>', r'$\1$', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<h1[^>]*>(.*?)</h1>', r'# \1', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<h2[^>]*>(.*?)</h2>', r'## \1', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<h3[^>]*>(.*?)</h3>', r'### \1', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<h4[^>]*>(.*?)</h4>', r'#### \1', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<b>(.*?)</b>', r'**\1**', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<strong>(.*?)</strong>', r'**\1**', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<i>(.*?)</i>', r'*\1*', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<em>(.*?)</em>', r'*\1*', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<a[^>]*href="([^"]*?)"[^>]*>(.*?)</a>', r'[\2](\1)', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<ol[^>]*>', '', text)
|
||||
text = re.sub(r'</ol>', '', text)
|
||||
text = re.sub(r'<ul[^>]*>', '', text)
|
||||
text = re.sub(r'</ul>', '', text)
|
||||
text = re.sub(r'<li[^>]*>', '- ', text)
|
||||
text = re.sub(r'</li>', '', text)
|
||||
text = re.sub(r'<blockquote[^>]*>', '> ', text)
|
||||
text = re.sub(r'</blockquote>', '', text)
|
||||
text = re.sub(r'<p[^>]*>', '', text)
|
||||
text = re.sub(r'</p>', '\n', text)
|
||||
text = re.sub(r'<hr[^>]*/>', '\n---\n', text)
|
||||
text = re.sub(r'<code>(.*?)</code>', r'`\1`', text, flags=re.DOTALL)
|
||||
text = re.sub(r'<[^>]+>', '', text)
|
||||
text = re.sub(r'\n{3,}', '\n\n', text)
|
||||
return text.strip()
|
||||
|
||||
count = 0
|
||||
for f in sorted(glob.glob(os.path.join(input_dir, '*.json'))):
|
||||
try:
|
||||
with open(f, 'r', encoding='utf-8') as fh:
|
||||
raw = fh.read()
|
||||
lines = raw.split('\n')
|
||||
json_lines = [l for l in lines if not l.startswith('2026/')]
|
||||
data = json.loads('\n'.join(json_lines))
|
||||
if not data.get('ok'):
|
||||
print(f'SKIP: {os.path.basename(f)}')
|
||||
continue
|
||||
doc = data['data']['document']
|
||||
doc_id = doc['document_id']
|
||||
title = ''
|
||||
content_html = doc['content']
|
||||
title_match = re.search(r'<title>(.*?)</title>', content_html)
|
||||
if title_match:
|
||||
title = title_match.group(1)
|
||||
md_content = html_to_md(content_html)
|
||||
md_path = os.path.join(output_dir, f'{doc_id}.md')
|
||||
with open(md_path, 'w', encoding='utf-8') as fh:
|
||||
if title:
|
||||
fh.write(f'# {title}\n\n')
|
||||
fh.write(md_content)
|
||||
fh.write(f'\n\n---\n*Source: feishu doc {doc_id}*\n')
|
||||
print(f'OK: {doc_id} -> {title[:60] if title else "(untitled)"} ({len(md_content)} chars)')
|
||||
count += 1
|
||||
except Exception as e:
|
||||
print(f'ERROR: {os.path.basename(f)}: {e}')
|
||||
|
||||
print(f'\nTotal: {count}')
|
||||
Reference in New Issue
Block a user