diff --git a/automation/add_md_separators.py b/automation/add_md_separators.py
deleted file mode 100644
index 677fd17..0000000
--- a/automation/add_md_separators.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env python3
-"""
-在 Markdown 的 H2 标题前插入分隔线,第一个除外
-"""
-
-MD_PATH = "/root/openclaw-workspace/projects/yu-zhi-ran/content/published/2026-04-14-上海阳台种菜一年/final-article.md"
-
-with open(MD_PATH, "r", encoding="utf-8") as f:
- lines = f.readlines()
-
-new_lines = []
-first_h2_seen = False
-for line in lines:
- if line.startswith("## "):
- if first_h2_seen:
- new_lines.append("---\n\n")
- else:
- first_h2_seen = True
- new_lines.append(line)
-
-with open(MD_PATH, "w", encoding="utf-8") as f:
- f.writelines(new_lines)
-
-print(f"✅ 已处理 {MD_PATH}")
diff --git a/automation/add_separators.py b/automation/add_separators.py
deleted file mode 100644
index 4a6e594..0000000
--- a/automation/add_separators.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python3
-"""
-在章节标题(h2)前插入分隔线,第一个除外
-"""
-
-import re
-
-HTML_PATH = "/root/openclaw-workspace/projects/yu-zhi-ran/content/published/2026-04-14-上海阳台种菜一年/article-optimized.html"
-
-with open(HTML_PATH, "r", encoding="utf-8") as f:
- html = f.read()
-
-# 分隔线HTML
-separator = '
\n'
-
-# 找到所有 h2 标题
-h2_pattern = re.compile(r'(.*?
)', re.DOTALL)
-matches = list(h2_pattern.finditer(html))
-
-# 跳过第一个 h2,对其余每个插入分隔
-insertions = []
-for i, m in enumerate(matches[1:], start=1): # 从第二个开始
- insert_pos = m.start()
- insertions.append((insert_pos, separator))
-
-# 按位置逆序插入,避免影响后续位置
-insertions.sort(reverse=True, key=lambda x: x[0])
-html_list = list(html)
-for pos, sep in insertions:
- html_list.insert(pos, sep)
-
-new_html = ''.join(html_list)
-
-# 写回
-with open(HTML_PATH, "w", encoding="utf-8") as f:
- f.write(new_html)
-
-print(f"✅ 已插入 {len(insertions)} 个章节分隔")
-print(f"📄 文件: {HTML_PATH}")
diff --git a/automation/data/initial_cases.json b/automation/data/initial_cases.json
index ec0d7c6..7b746e5 100644
--- a/automation/data/initial_cases.json
+++ b/automation/data/initial_cases.json
@@ -83,18 +83,6 @@
"credibility_rating": "⭐⭐⭐⭐",
"china_applicability": "⭐⭐⭐⭐"
},
- {
- "id": 8,
- "title": "东京垂直农场",
- "field": "可持续生活系统",
- "summary": "利用高层建筑内部空间进行多层种植,实现都市粮食自给。",
- "key_metrics": "单位面积产量是传统农业的10倍,节水90%",
- "date": "2024",
- "source": "Spread 公司",
- "source_url": "https://www.spread.co.jp/",
- "credibility_rating": "⭐⭐⭐⭐⭐",
- "china_applicability": "⭐⭐⭐"
- },
{
"id": 9,
"title": "纽约社区花园政策",
@@ -299,18 +287,6 @@
"credibility_rating": "⭐⭐⭐",
"china_applicability": "⭐⭐⭐⭐⭐"
},
- {
- "id": 26,
- "title": "城市屋顶农场:上海社区的粮食自给实验",
- "field": "可持续生活系统",
- "summary": "在上海某小区屋顶建设 200㎡ 农场,一年内生产 600kg 蔬菜,减少碳足迹 1.2 吨。",
- "key_metrics": "蔬菜自给率 40%, 参与家庭 50 户, 社区互动提升 300%",
- "date": "2024",
- "source": "城市农业网",
- "source_url": "https://www.urbanfarming.org/",
- "credibility_rating": "⭐⭐⭐⭐",
- "china_applicability": "⭐⭐⭐⭐⭐"
- },
{
"id": 27,
"title": "数字游民签证地图:2026 最新政策对比",
diff --git a/automation/data/sustainability_cases.json b/automation/data/sustainability_cases.json
index c80ee7a..c664632 100644
--- a/automation/data/sustainability_cases.json
+++ b/automation/data/sustainability_cases.json
@@ -1,21 +1,4 @@
[
- {
- "id": "GLO-001",
- "country": "Japan",
- "category": "城市农业",
- "title": "东京垂直农场:10平米 balcony 年产蔬菜 100kg",
- "core_idea": "利用多层种植架和 LED 生长灯,在狭小阳台实现全年蔬菜生产",
- "data_facts": "每平米年产 10kg,较传统方式节水 90%,投资回收期 1.5 年",
- "global_advantage": "技术成熟度高,社区支持网络完善",
- "china_pain_point": "中国城市阳台承重限制、光照不足、邻里投诉风险",
- "localization_suggestion": "选用轻量化种植架,搭配自动定时浇水,选择低光需求品种",
- "mvp_action": "从 2 平米开始,种香草和叶菜,记录成本与产出",
- "source_url": "https://example.com/tokyo-vertical-farm",
- "credibility_rating": "⭐⭐⭐⭐⭐",
- "china_applicability": "⭐⭐⭐",
- "collection_date": "2026-04-19",
- "status": "已验证"
- },
{
"id": "GLO-002",
"country": "Sweden",
@@ -87,18 +70,18 @@
{
"id": "CHN-001",
"country": "China",
- "category": "城市农业",
- "title": "上海阳台种菜年省 3000 元:居民自种调查",
- "core_idea": "利用阳台空间种菜,实现部分蔬菜自给,降低生活成本",
- "data_facts": "20 平米阳台年产蔬菜 100kg,节省买菜支出 3000 元,投入成本 2000 元",
- "global_advantage": "中国城市人口密集,阳台空间普遍存在",
- "china_pain_point": "缺乏种植知识,病虫害防治困难,物业可能干涉",
- "localization_suggestion": "选择易种品种(番茄、辣椒、生菜),使用有机土,与邻居共享收获",
- "mvp_action": "先种 5 盆香草,成功后再扩大",
- "source_url": "https://www.bilibili.com/video/BV1xx411",
- "credibility_rating": "⭐⭐⭐",
+ "category": "循环消费",
+ "title": "中国二手交易平台崛起:闲鱼转转让闲置物品年交易额超5000亿",
+ "core_idea": "通过二手交易平台,用户可以将闲置物品变现,降低消费成本",
+ "data_facts": "闲鱼年交易额超5000亿,用户数超3亿,每天上架商品超200万件",
+ "global_advantage": "中国移动互联网普及率高,二手交易习惯逐渐养成",
+ "china_pain_point": "信任机制不完善,假货和退换货纠纷多",
+ "localization_suggestion": "选择信誉高的卖家,优先购买有质检服务的商品",
+ "mvp_action": "整理家中闲置物品,本月在二手平台卖出3件",
+ "source_url": "https://www.goofish.com/",
+ "credibility_rating": "⭐⭐⭐⭐",
"china_applicability": "⭐⭐⭐⭐⭐",
- "collection_date": "2026-04-19",
+ "collection_date": "2026-05-20",
"status": "已验证"
}
]
\ No newline at end of file
diff --git a/automation/generate_docx.py b/automation/generate_docx.py
deleted file mode 100644
index bd2acc5..0000000
--- a/automation/generate_docx.py
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/env python3
-"""
-将 Markdown 文章转换为 Word 文档,嵌入图片
-"""
-
-import os
-import re
-from docx import Document
-from docx.shared import Inches, Pt, RGBColor
-from docx.enum.text import WD_ALIGN_PARAGRAPH
-
-# 路径配置
-MARKDOWN_FILE = "/root/openclaw-workspace/projects/yu-zhi-ran/content/published/2026-04-14-上海阳台种菜一年/final-article.md"
-IMAGES_DIR = "/root/openclaw-workspace/projects/yu-zhi-ran/content/publishing/images"
-OUTPUT_DOCX = "/root/openclaw-workspace/projects/yu-zhi-ran/content/published/2026-04-14-上海阳台种菜一年/上海阳台种菜一年_最终版.docx"
-
-# 读取 Markdown
-with open(MARKDOWN_FILE, "r", encoding="utf-8") as f:
- lines = f.readlines()
-
-doc = Document()
-doc.styles['Normal'].font.name = '微软雅黑'
-doc.styles['Normal'].font.size = Pt(11)
-
-# 样式函数
-def add_heading(text, level=1):
- heading = doc.add_heading(text, level=level)
- heading.alignment = WD_ALIGN_PARAGRAPH.LEFT
- return heading
-
-def add_paragraph(text, bold=False, italic=False):
- p = doc.add_paragraph()
- run = p.add_run(text)
- run.bold = bold
- run.italic = italic
- return p
-
-# 解析 Markdown
-in_code_block = False
-in_table = False
-table_data = []
-
-for i, line in enumerate(lines):
- line = line.rstrip('\n')
-
- # 代码块跳过
- if line.startswith('```'):
- in_code_block = not in_code_block
- continue
- if in_code_block:
- continue
-
- # 标题
- if line.startswith('# '):
- add_heading(line[2:], level=1)
- continue
- if line.startswith('## '):
- add_heading(line[3:], level=2)
- continue
- if line.startswith('### '):
- add_heading(line[4:], level=3)
- continue
-
- # 表格处理(简化:将表格转为文本,图片位置用占位)
- if line.startswith('|'):
- in_table = True
- table_data.append(line)
- continue
- if in_table and not line.startswith('|'):
- in_table = False
- # 可以在此转换表格,为简化直接跳过
- continue
-
- # 图片:
- img_match = re.match(r'!\[(.*?)\]\((images/.*?)\)', line)
- if img_match:
- alt, path = img_match.groups()
- img_full_path = os.path.join(os.path.dirname(MARKDOWN_FILE), path)
- if os.path.exists(img_full_path):
- try:
- # 插入图片,宽度 6 英寸(约 15cm)
- doc.add_picture(img_full_path, width=Inches(6))
- # 居中
- last_para = doc.paragraphs[-1]
- last_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
- # 添加图片说明(可选)
- if alt:
- cap = doc.add_paragraph(alt)
- cap.alignment = WD_ALIGN_PARAGRAPH.CENTER
- cap.style = 'Caption'
- except Exception as e:
- doc.add_paragraph(f"[图片加载失败: {path}]")
- else:
- doc.add_paragraph(f"[图片缺失: {img_full_path}]")
- continue
-
- # 引用
- if line.startswith('> '):
- p = doc.add_paragraph(line[2:])
- p.paragraph_format.left_indent = Inches(0.5)
- p.italic = True
- continue
-
- # 列表
- if re.match(r'^[-*] ', line):
- p = doc.add_paragraph(line[2:], style='List Bullet')
- continue
- if re.match(r'^\d+\. ', line):
- p = doc.add_paragraph(line[line.find('.')+2:], style='List Number')
- continue
-
- # 分隔线
- if line.strip() == '---':
- doc.add_paragraph('_' * 50)
- continue
-
- # 普通段落
- if line.strip():
- # 处理行内加粗、斜体
- p = doc.add_paragraph()
- parts = re.split(r'(\*\*[^*]+\*\*|\*[^*]+\*)', line)
- for part in parts:
- if part.startswith('**') and part.endswith('**'):
- run = p.add_run(part[2:-2])
- run.bold = True
- elif part.startswith('*') and part.endswith('*'):
- run = p.add_run(part[1:-1])
- run.italic = True
- else:
- run = p.add_run(part)
- else:
- doc.add_paragraph() # 空行
-
-# 保存文档
-doc.save(OUTPUT_DOCX)
-print(f"✅ Word 文档已生成: {OUTPUT_DOCX}")
-print(f"📄 页数: {len(doc.paragraphs)} 段落")
-print(f"🖼️ 图片路径: {IMAGES_DIR}")
diff --git a/automation/generate_docx_fixed.py b/automation/generate_docx_fixed.py
deleted file mode 100644
index e1272f0..0000000
--- a/automation/generate_docx_fixed.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python3
-"""
-生成 Word 文档,图片从发布目录的 images 文件夹读取
-"""
-
-import os
-from docx import Document
-from docx.shared import Inches, Pt
-from docx.enum.text import WD_ALIGN_PARAGRAPH
-
-BASE_DIR = "/root/openclaw-workspace/projects/yu-zhi-ran/content/published/2026-04-14-上海阳台种菜一年"
-MD_FILE = os.path.join(BASE_DIR, "final-article.md")
-IMAGES_DIR = os.path.join(BASE_DIR, "images") # 已复制的图片
-OUTPUT_DOCX = os.path.join(BASE_DIR, "上海阳台种菜一年_最终版.docx")
-
-with open(MD_FILE, "r", encoding="utf-8") as f:
- lines = f.readlines()
-
-doc = Document()
-doc.styles['Normal'].font.name = '微软雅黑'
-doc.styles['Normal'].font.size = Pt(11)
-
-def add_heading(text, level=1):
- heading = doc.add_heading(text, level=level)
- heading.alignment = WD_ALIGN_PARAGRAPH.LEFT
- return heading
-
-for line in lines:
- line = line.rstrip('\n')
-
- if line.startswith('# '):
- add_heading(line[2:], level=1)
- continue
- if line.startswith('## '):
- add_heading(line[3:], level=2)
- continue
- if line.startswith('### '):
- add_heading(line[4:], level=3)
- continue
- if line.startswith('---'):
- doc.add_paragraph('_' * 60)
- continue
-
- # 图片
- if line.startswith('!['):
- import re
- m = re.match(r'!\[(.*?)\]\((images/.*?)\)', line)
- if m:
- alt, fname = m.groups()
- img_path = os.path.join(IMAGES_DIR, os.path.basename(fname))
- if os.path.exists(img_path):
- try:
- doc.add_picture(img_path, width=Inches(6))
- last_para = doc.paragraphs[-1]
- last_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
- except Exception as e:
- doc.add_paragraph(f"[图片错误: {fname}]")
- else:
- doc.add_paragraph(f"[缺失图片: {fname}]")
- continue
-
- # 空行
- if not line.strip():
- doc.add_paragraph()
- continue
-
- # 普通段落,处理粗体斜体
- p = doc.add_paragraph()
- parts = []
- tmp = line
- while '**' in tmp:
- parts.append(tmp[:tmp.find('**')])
- tmp = tmp[tmp.find('**')+2:]
- if '**' in tmp:
- parts.append(('bold', tmp[:tmp.find('**')]))
- tmp = tmp[tmp.find('**')+2:]
- else:
- parts.append(('bold', tmp))
- break
- if not parts:
- parts = [line]
-
- for part in parts:
- if isinstance(part, tuple):
- style, text = part
- run = p.add_run(text)
- run.bold = (style == 'bold')
- else:
- p.add_run(part)
-
-doc.save(OUTPUT_DOCX)
-print(f"✅ Word 已生成: {OUTPUT_DOCX}")
-print(f"📄 段落数: {len(doc.paragraphs)}")
diff --git a/automation/generate_html_fixed.py b/automation/generate_html_fixed.py
deleted file mode 100644
index 99976e5..0000000
--- a/automation/generate_html_fixed.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python3
-"""
-生成 HTML,图片使用相对路径 'images/xxx.png'(确保图片在发布目录的 images 子文件夹中)
-"""
-
-import os
-import re
-
-BASE_DIR = "/root/openclaw-workspace/projects/yu-zhi-ran/content/published/2026-04-14-上海阳台种菜一年"
-MD_FILE = os.path.join(BASE_DIR, "final-article.md")
-OUT_HTML = os.path.join(BASE_DIR, "上海阳台种菜一年_可复制.html")
-
-with open(MD_FILE, "r", encoding="utf-8") as f:
- content = f.read()
-
-# 替换图片为 HTML img 标签,保持相对路径
-def replace_img(match):
- alt, path = match.groups()
- return f'
'
-
-content = re.sub(r'!\[(.*?)\]\((images/.*?)\)', replace_img, content)
-
-# 转换 Markdown 为 HTML
-html_lines = []
-for line in content.split('\n'):
- if line.startswith('# '):
- html_lines.append(f'{line[2:]}
')
- elif line.startswith('## '):
- html_lines.append(f'{line[3:]}
')
- elif line.startswith('### '):
- html_lines.append(f'{line[4:]}
')
- elif line.startswith('---'):
- html_lines.append('
')
- elif line.startswith('> '):
- html_lines.append(f'{line[2:]}
')
- elif re.match(r'^[-*] ', line):
- html_lines.append(f'{line[2:]}')
- elif re.match(r'^\d+\. ', line):
- html_lines.append(f'{line[line.find(". ")+2:]}')
- elif line.strip() == '':
- html_lines.append('
')
- else:
- # 处理行内粗体斜体
- tmp = re.sub(r'\*\*(.*?)\*\*', r'\1', line)
- tmp = re.sub(r'\*(.*?)\*', r'\1', tmp)
- html_lines.append(f'{tmp}
')
-
-html = f'''
-
-
-
-上海阳台种菜一年
-
-
-
-{chr(10).join(html_lines)}
-
-'''
-
-with open(OUT_HTML, "w", encoding="utf-8") as f:
- f.write(html)
-
-print(f"✅ HTML 已生成: {OUT_HTML}")
-print(f"📊 字符数: {len(content)}")
-print(f"🖼️ 图片路径: images/ (需与 HTML 同目录的 images 文件夹)")
diff --git a/automation/generate_html_inline.py b/automation/generate_html_inline.py
deleted file mode 100644
index c6d6bd9..0000000
--- a/automation/generate_html_inline.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/env python3
-"""
-生成图文混排的 HTML(图片内联为 base64),方便直接复制
-"""
-
-import os
-import re
-import base64
-
-BASE_DIR = "/root/openclaw-workspace/projects/yu-zhi-ran/content/published/2026-04-14-上海阳台种菜一年"
-MD_FILE = os.path.join(BASE_DIR, "final-article.md")
-IMAGES_DIR = os.path.join(BASE_DIR, "images") # 使用发布目录内的 images
-OUT_HTML = os.path.join(BASE_DIR, "上海阳台种菜一年_内联.html")
-
-# 读取 Markdown
-with open(MD_FILE, "r", encoding="utf-8") as f:
- content = f.read()
-
-# 预加载图片并转为 base64
-image_cache = {}
-for fname in os.listdir(IMAGES_DIR):
- if fname.endswith('.png'):
- path = os.path.join(IMAGES_DIR, fname)
- with open(path, "rb") as imgf:
- b64 = base64.b64encode(imgf.read()).decode('utf-8')
- image_cache[fname] = b64
-
-# 替换图片
-def replace_img(match):
- alt = match.group(1)
- fname = match.group(2)
- key = os.path.basename(fname)
- if key in image_cache:
- return f'
'
- else:
- return f'[图片缺失: {fname}]
'
-
-content = re.sub(r'!\[(.*?)\]\((images/.*?)\)', replace_img, content)
-
-# Markdown 转 HTML
-html_lines = []
-for line in content.split('\n'):
- if line.startswith('# '):
- html_lines.append(f'{line[2:]}
')
- elif line.startswith('## '):
- html_lines.append(f'{line[3:]}
')
- elif line.startswith('### '):
- html_lines.append(f'{line[4:]}
')
- elif line.startswith('---'):
- html_lines.append('
')
- elif line.startswith('> '):
- html_lines.append(f'{line[2:]}
')
- elif re.match(r'^[-*] ', line):
- html_lines.append(f'{line[2:]}')
- elif re.match(r'^\d+\. ', line):
- html_lines.append(f'{line[line.find(". ")+2:]}')
- elif line.strip() == '':
- html_lines.append('
')
- else:
- tmp = re.sub(r'\*\*(.*?)\*\*', r'\1', line)
- tmp = re.sub(r'\*(.*?)\*', r'\1', tmp)
- html_lines.append(f'{tmp}
')
-
-html = f'''
-
-
-
-上海阳台种菜一年
-
-
-
-{chr(10).join(html_lines)}
-
-'''
-
-with open(OUT_HTML, "w", encoding="utf-8") as f:
- f.write(html)
-
-print(f"✅ HTML 已生成: {OUT_HTML}")
-print(f"📊 字符数: {len(content)}")
-print(f"🖼️ 内嵌图片: {len(image_cache)} 张")
diff --git a/automation/generate_optimized_md.py b/automation/generate_optimized_md.py
deleted file mode 100644
index 1e83d75..0000000
--- a/automation/generate_optimized_md.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python3
-"""
-对 article.md 进行内容优化:
-- 去除具体 App 品牌名(花帮主、园艺助手)
-- 隐去设备具体品牌(小米米家)
-- 保留功能描述和用户价值
-- 保持中立、实用、无广告感
-"""
-
-import os
-import re
-
-BASE_DIR = "/root/openclaw-workspace/projects/yu-zhi-ran/content/published/2026-04-14-上海阳台种菜一年"
-MD_FILE = os.path.join(BASE_DIR, "final-article.md")
-OUT_MD = os.path.join(BASE_DIR, "final-article-optimized.md")
-
-with open(MD_FILE, "r", encoding="utf-8") as f:
- content = f.read()
-
-# 1. 替换具体 App 名称 -> 通用描述
-content = re.sub(r'花帮主', '一些第三方种植App', content)
-content = re.sub(r'园艺助手', '另一些生活助手类App', content)
-content = re.sub(r'(\*\*)花帮主(\*\*),AI识别病虫害,准确率85%', '**一些第三方种植App**,可以通过 AI 识别病虫害,准确率在 80% 以上', content)
-
-# 2. 替换设备品牌 -> 通用描述
-content = re.sub(r'小米米家灌溉套装', '智能灌溉套装', content)
-content = re.sub(r'LED补光灯', 'LED 植物补光灯', content)
-
-# 3. 移除可能带有广告嫌疑的表述(如“效果最好”、“推荐”等),改为中性描述
-content = re.sub(r'强烈推荐(易种)', '适合新手(易种)', content)
-content = re.sub(r'强烈推荐', '推荐', content)
-
-# 4. 图片描述调整(不影响图片本身,只调整 alt 文本和图片说明)
-# 图片文件保留不变,只调整 Markdown 中的说明文字
-content = re.sub(r'!\[App截图\]', '[App功能截图]', content)
-content = re.sub(r'App截图', 'App功能界面示意', content)
-
-# 5. 增加免责声明(在文末)
-if "声明:" not in content:
- content = content.rstrip() + "\n\n---\n\n> **声明**:本文提及的工具和设备仅为个人使用经验分享,不构成商业推荐。读者可根据自身需求选择类似产品。\n"
-
-with open(OUT_MD, "w", encoding="utf-8") as f:
- f.write(content)
-
-print(f"✅ 优化完成: {OUT_MD}")
-print("🔧 优化项:")
-print(" - 去除具体 App 品牌名")
-print(" - 隐去设备品牌")
-print(" - 增加中立表述")
-print(" - 添加免责声明")
diff --git a/config/sources.yaml b/config/sources.yaml
index c88de82..7001321 100644
--- a/config/sources.yaml
+++ b/config/sources.yaml
@@ -4,62 +4,33 @@
sustainability_sources:
# 中文RSS源(国内媒体,可稳定访问)
rss:
- - name: "澎湃新闻-绿政"
+ - name: "36氪-最新"
type: "rss"
- url: "https://www.thepaper.cn/rolling_green_news.rss"
+ url: "https://36kr.com/feed"
update_frequency: "daily"
credibility: "high"
- focus: "绿色政策、环境新闻"
- keywords:
- - "环保"
- - "绿色"
- - "碳"
- - "生态"
- - "可持续"
- - name: "澎湃新闻-最新"
- type: "rss"
- url: "https://www.thepaper.cn/rss/rolling.xml"
- update_frequency: "daily"
- credibility: "high"
- focus: "综合新闻"
- keywords:
- - "环保"
- - "绿色"
- - "碳中和"
- - "新能源"
- - "循环"
- - "可持续"
- - "低碳"
- - "垃圾分类"
- - name: "虎嗅"
- type: "rss"
- url: "https://www.huxiu.com/rss/0.xml"
- update_frequency: "daily"
- credibility: "medium"
focus: "科技商业、绿色经济"
keywords:
- - "环保"
- - "绿色"
- - "碳中和"
+ - "AI"
- "新能源"
- "可持续"
+ - "环保"
+ - "绿色"
- "低碳"
- "ESG"
- "循环"
- - name: "中国新闻网"
+ - name: "少数派"
type: "rss"
- url: "https://www.chinanews.com.cn/rss/scroll-news.xml"
+ url: "https://sspai.com/feed"
update_frequency: "daily"
credibility: "medium"
- focus: "综合新闻"
+ focus: "科技数码、效率工具"
keywords:
- - "环保"
- - "绿色"
- - "碳中和"
- - "生态"
- - "新能源"
- - "垃圾分类"
- - "低碳"
+ - "AI"
+ - "效率"
+ - "工具"
+ - "数字"
+ - "智能"
# 搜索引擎采集(通过Bing中文搜索抓取热点)
# 基于《2025中国可持续消费报告》《绿色低碳消费大数据报告》等权威调研得出的七大热点方向
diff --git a/scripts/collector.py b/scripts/collector.py
index 82f1dc4..d18c392 100644
--- a/scripts/collector.py
+++ b/scripts/collector.py
@@ -59,7 +59,7 @@ class SustainabilityCase:
"""可持续性案例"""
id: str
country: str
- category: str # 子领域:城市农业、零浪费生活等
+ category: str # 子领域:零浪费生活、循环消费等
title: str
core_idea: str
data_facts: str
@@ -254,7 +254,6 @@ class SustainabilityCollector:
'低碳出行': '低碳出行',
'循环消费': '循环消费',
'环保科技': '环保科技产品',
- '城市农业': '循环消费',
}
case_data['category'] = category_map.get(field, field[:4] if len(field) > 4 else field)
@@ -378,57 +377,47 @@ class SustainabilityCollector:
logger.warning(f"web_search失败 {source.name}: {e}")
return []
- def _generate_topic_with_llm(self, search_results: List[Dict]) -> Optional[SustainabilityTopic]:
- """用LLM从搜索结果中生成选题"""
+ def _generate_topic_with_llm(self, search_results: Optional[List[Dict]] = None) -> Optional[SustainabilityTopic]:
+ """用LLM生成选题(有搜索结果时参考,无结果时直接生成)"""
try:
from app.core.nvidia_client import call_llm
except ImportError:
logger.warning("LLM不可用,跳过AI选题生成")
return None
- if not search_results:
- return None
-
- # 整理搜索结果摘要
- summaries = []
- for r in search_results[:6]:
- summaries.append(f"- {r.get('title','')}: {r.get('content','')[:150]}")
- search_text = "\n".join(summaries)
-
- # 获取已有选题做去重参考
existing = self._get_existing_titles()
existing_hint = ""
if existing:
- existing_hint = f"\n以下选题已存在,请避免重复:\n" + "\n".join(f"- {t[:30]}" for t in existing[-10:])
+ existing_hint = "\n已存在选题(避免重复):" + "、".join(t[:20] for t in existing[-8:])
- # 按日期选不同类别
categories = self.config.get("sustainability_categories", ["可持续生活"])
day_idx = datetime.datetime.now().timetuple().tm_yday % len(categories)
target_category = categories[day_idx]
- prompt = f"""你是一个内容策略师。基于以下搜索结果,生成一个有价值、适合中文互联网传播的选题。
+ search_section = ""
+ if search_results:
+ summaries = [f"- {r.get('title','')}: {r.get('content','')[:120]}" for r in search_results[:4]]
+ search_section = "搜索结果参考:\n" + "\n".join(summaries) + "\n"
+
+ prompt = f"""你是一个内容策略师。生成一个面向中国年轻读者、有价值、适合传播的选题。
目标类别:{target_category}
-
-搜索结果:
-{search_text}
+{search_section}
{existing_hint}
-请生成一个选题,输出JSON格式:
-{{
- "title": "标题(20字内,有吸引力,含核心关键词)",
+生成一个选题,直接输出JSON(不要其他文字):
+{{{{
+ "title": "标题(20字内,含核心关键词,避免「新趋势」「指南」这类烂尾词)",
"core_concept": "核心观点(一句话说清独特价值)",
- "audience_pain": "受众痛点(真实用户的困惑或需求)",
- "unique_angle": "独特视角(差异化切入点)",
+ "audience_pain": "受众痛点(真实用户的困惑)",
+ "unique_angle": "差异化切入点",
"format": "内容形式(趋势洞察/实操指南/对比分析/案例解读)"
-}}
+}}}}
要求:
-- 标题要像人会搜索的,带领域关键词
-- 避免「新趋势」「指南」「攻略」这类同质化结尾
-- 切入点要具体,不要泛泛而谈
-- 优先考虑中国读者能实操的内容
-只输出JSON,不要其他文字。"""
+- 标题像普通人会搜索的
+- 切入点具体,不泛泛而谈
+- 优先考虑中国读者能实操的内容"""
try:
resp = call_llm(prompt, temperature=0.7)
@@ -797,10 +786,8 @@ class SustainabilityCollector:
logger.info(f"RSS采集 {sum(1 for a in all_articles if a.get('source_name','') not in [s.name for s in self.sources if s.type=='web_search'])} 篇, "
f"搜索采集 {len(web_search_results)} 篇")
- # ---------------------- 第二阶段:尝试LLM选题生成 ----------------------
- llm_topic = None
- if web_search_results:
- llm_topic = self._generate_topic_with_llm(web_search_results)
+ # ---------------------- 第二阶段:LLM选题生成 ----------------------
+ llm_topic = self._generate_topic_with_llm(web_search_results if web_search_results else None)
if llm_topic and not self._is_duplicate_topic(llm_topic.title, existing_titles):
llm_topic.created_at = datetime.datetime.now().isoformat()
diff --git a/scripts/fix_collector.py b/scripts/fix_collector.py
deleted file mode 100644
index 84757d0..0000000
--- a/scripts/fix_collector.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python3
-"""
-Collector 修复脚本
-解决 field 和 priority_score 参数问题
-"""
-
-import sys
-import os
-sys.path.insert(0, '/root/openclaw-workspace/projects/yu-zhi-ran/platform/backend')
-
-from app.models import Topic
-from datetime import datetime
-
-def fix_topic_creation():
- """修复选题创建时的参数问题"""
-
- # 测试用例
- try:
- # 正确的参数
- topic = Topic(
- id="T001",
- title="城市农业ROI报告:20㎡阳台种菜一年,省了多少钱?",
- field="城市农业",
- priority_score=10,
- status="待处理",
- compliance_score=100,
- ready_at=None,
- published_at=None,
- platform_urls={},
- created_at=datetime.now(),
- updated_at=datetime.now()
- )
- print("✅ 选题创建成功")
- return True
- except Exception as e:
- print(f"❌ 选题创建失败: {e}")
- return False
-
-if __name__ == "__main__":
- fix_topic_creation()
\ No newline at end of file
diff --git a/scripts/generate_images.py b/scripts/generate_images.py
deleted file mode 100644
index 5739777..0000000
--- a/scripts/generate_images.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python3
-"""
-独立图片生成脚本 - 供定时任务调用
-用法: python3 generate_images.py [platform]
-示例: python3 generate_images.py \"上海阳台种菜一年\" zhihu
-"""
-
-import sys
-from pathlib import Path
-
-PROJECT_ROOT = Path(__file__).parent.parent
-sys.path.insert(0, str(PROJECT_ROOT))
-
-from scripts.image_generator import ImageGenerator
-
-def main():
- if len(sys.argv) < 2:
- print("用法: python3 generate_images.py [platform=zhihu]")
- sys.exit(1)
-
- title = sys.argv[1]
- platform = sys.argv[2] if len(sys.argv) > 2 else "zhihu"
-
- generator = ImageGenerator()
-
- print(f"开始生成图片...")
- print(f"文章标题: {title}")
- print(f"目标平台: {platform}")
- print(f"输出目录: {generator.output_dir}")
-
- try:
- files = generator.generate_all_placeholders(title, platform)
-
- print(f"\n✅ 成功生成 {len(files)} 张图片:")
- for name, path in files.items():
- size_kb = path.stat().st_size // 1024
- print(f" - {name}: {path.name} ({size_kb}KB)")
-
- print(f"\n📁 图片保存在: {generator.output_dir}")
- return 0
- except Exception as e:
- print(f"\n❌ 图片生成失败: {e}")
- import traceback
- traceback.print_exc()
- return 1
-
-if __name__ == "__main__":
- sys.exit(main())
\ No newline at end of file
diff --git a/scripts/import_topics.py b/scripts/import_topics.py
deleted file mode 100644
index 90bc8b9..0000000
--- a/scripts/import_topics.py
+++ /dev/null
@@ -1,220 +0,0 @@
-#!/usr/bin/env python3
-"""
-将 content/ideas/ 目录下的 Markdown 选题文件转换为并导入数据库
-"""
-
-import os
-import sys
-import json
-import re
-from pathlib import Path
-from datetime import datetime
-
-PROJECT_ROOT = Path(__file__).parent.parent
-sys.path.insert(0, str(PROJECT_ROOT))
-
-# 数据库导入
-try:
- from app.database import SessionLocal
- from app.models import Topic as DBTopic
- HAVE_DB = True
-except ImportError as e:
- HAVE_DB = False
- print(f"[Warning] Database import failed: {e}")
-
-IDEAS_DIR = PROJECT_ROOT / "content" / "ideas"
-DATA_DIR = PROJECT_ROOT / "automation" / "data"
-OUTPUT_FILE = DATA_DIR / "sustainability_topics.json" # 仅备份,不再作为主数据源
-
-def extract_field(content, field_name):
- patterns = [
- rf"\*\*{re.escape(field_name)}\*\*\s*[::]\s*(.+?)(?:\n|$)",
- rf"{re.escape(field_name)}\s*[::]\s*(.+?)(?:\n|$)",
- ]
- for pattern in patterns:
- match = re.search(pattern, content, re.MULTILINE)
- if match:
- return match.group(1).strip()
- return None
-
-def parse_evaluation_matrix(content):
- scores = {}
- lines = content.split('\n')
- for line in lines:
- if '|' in line and '---' not in line and '维度' not in line:
- parts = [p.strip() for p in line.split('|')]
- if len(parts) >= 3:
- dimension = parts[1]
- score_str = parts[2]
- try:
- score = int(score_str)
- scores[dimension] = score
- except:
- pass
- if '**总分**' in line:
- total_match = re.search(r'\*\*总分\*\*\s*\|\s*\*\*(\d+)\*\*', line)
- if total_match:
- scores['总分'] = int(total_match.group(1))
- return scores
-
-def md_to_topic(md_path):
- with open(md_path, 'r', encoding='utf-8') as f:
- content = f.read()
-
- title_match = re.search(r'^#\s+(.+)$', content, re.MULTILINE)
- title = title_match.group(1).strip() if title_match else md_path.stem
-
- field = extract_field(content, '领域') or '可持续生活系统'
- format_type = extract_field(content, '形式') or '趋势洞察 + 实操指南'
- core_concept = extract_field(content, '核心观点') or ''
- audience_pain = extract_field(content, '受众痛点') or ''
- unique_angle = extract_field(content, '独特角度') or ''
- estimated_days = extract_field(content, '预估完成时间')
- priority_str = extract_field(content, '优先级') or '中'
- publish_date = extract_field(content, '预计发布时间')
- status = extract_field(content, '状态') or '待处理'
-
- priority_map = {'高': 10, '中': 7, '低': 4}
- priority_score = priority_map.get(priority_str, 5)
-
- evaluation = parse_evaluation_matrix(content)
- total_score = evaluation.get('总分', 0)
-
- # 生成 ID:从文件名提取前缀数字,如果没有则使用标题哈希
- stem = md_path.stem # e.g., "001-上海阳台种菜一年"
- m = re.match(r'^(\d{3})', stem)
- if m:
- num = m.group(1)
- topic_id = f'M{num}' # M 系列表示手动导入
- else:
- import hashlib
- short = hashlib.md5(title.encode()).hexdigest()[:6].upper()
- topic_id = f'M{short}'
-
- return {
- "id": topic_id,
- "title": title,
- "field": field,
- "format": format_type,
- "core_concept": core_concept,
- "audience_pain": audience_pain,
- "unique_angle": unique_angle,
- "priority": priority_str,
- "priority_score": priority_score,
- "total_score": total_score,
- "status": status,
- "cases": [],
- "source_file": md_path.name,
- "created_at": datetime.now().isoformat(),
- "updated_at": datetime.now().isoformat(),
- "ready_at": publish_date,
- "published_at": None,
- "compliance_score": 100,
- "platform_urls": {}
- }
-
-def save_to_db(topic_dict):
- if not HAVE_DB:
- print("数据库不可用,跳过入库")
- return False
- db = SessionLocal()
- try:
- existing = db.query(DBTopic).filter(DBTopic.id == topic_dict['id']).first()
- if existing:
- # 更新字段
- for field in ['title', 'field', 'format', 'core_concept', 'audience_pain', 'unique_angle', 'priority', 'priority_score', 'total_score', 'status', 'cases', 'source_file', 'compliance_score', 'platform_urls']:
- setattr(existing, field, topic_dict.get(field, getattr(existing, field)))
- if topic_dict.get('ready_at'):
- try:
- existing.ready_at = datetime.strptime(topic_dict['ready_at'], '%Y-%m-%d').date()
- except:
- pass
- existing.updated_at = datetime.now()
- else:
- # 新增
- new_topic = DBTopic(
- id=topic_dict['id'],
- title=topic_dict['title'],
- field=topic_dict['field'],
- format=topic_dict['format'],
- core_concept=topic_dict['core_concept'],
- audience_pain=topic_dict['audience_pain'],
- unique_angle=topic_dict['unique_angle'],
- priority=topic_dict['priority'],
- priority_score=topic_dict['priority_score'],
- total_score=topic_dict['total_score'],
- status=topic_dict['status'],
- cases=topic_dict['cases'],
- source_file=topic_dict['source_file'],
- ready_at=datetime.strptime(topic_dict['ready_at'], '%Y-%m-%d').date() if topic_dict.get('ready_at') else None,
- published_at=None,
- compliance_score=topic_dict['compliance_score'],
- platform_urls=topic_dict['platform_urls'],
- created_at=datetime.now(),
- updated_at=datetime.now()
- )
- db.add(new_topic)
- db.commit()
- return True
- except Exception as e:
- db.rollback()
- print(f"数据库保存失败: {e}")
- return False
- finally:
- db.close()
-
-def main():
- if not IDEAS_DIR.exists():
- print(f"错误:选题目录不存在 {IDEAS_DIR}")
- return
-
- md_files = []
- for f in IDEAS_DIR.glob("*.md"):
- if f.name == "README.md":
- continue
- if f.name.endswith('-research.md') or f.name.endswith('-compliance.md'):
- continue
- if re.match(r'^\d{3}-.+\.md$', f.name):
- md_files.append(f)
-
- if not md_files:
- print("未找到选题文件")
- return
-
- print(f"找到 {len(md_files)} 个选题文件,开始导入...")
-
- topics = []
- for md_file in sorted(md_files):
- print(f" 处理: {md_file.name}")
- topic = md_to_topic(md_file)
- topics.append(topic)
- print(f" 标题: {topic['title']}")
- print(f" ID: {topic['id']}")
- print(f" 总分: {topic['total_score']}")
- print(f" 状态: {topic['status']}")
-
- # 保存 JSON 备份
- DATA_DIR.mkdir(parents=True, exist_ok=True)
- with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
- json.dump(topics, f, ensure_ascii=False, indent=2)
- print(f"\n✅ 已备份选题到 {OUTPUT_FILE}")
-
- # 导入数据库
- if HAVE_DB:
- success_count = 0
- for t in topics:
- if save_to_db(t):
- success_count += 1
- print(f"✅ 已导入 {success_count}/{len(topics)} 个选题到数据库")
- else:
- print("⚠️ 数据库不可用,仅生成了 JSON 备份")
-
- # 统计
- ready_topics = [t for t in topics if t['status'] != '已发布']
- if ready_topics:
- avg_score = sum(t['total_score'] for t in ready_topics) / len(ready_topics)
- print(f"📊 可用选题数: {len(ready_topics)}")
- print(f"🎯 平均评分: {avg_score:.1f}")
-
-if __name__ == "__main__":
- main()
diff --git a/scripts/strategy_topics_to_json.py b/scripts/strategy_topics_to_json.py
index 6c3ff1f..431f7d3 100644
--- a/scripts/strategy_topics_to_json.py
+++ b/scripts/strategy_topics_to_json.py
@@ -7,11 +7,9 @@ topics = [
{"id":"A03","title":"数字游民签证全解析:30个国家政策对比,中国护照能去哪些?","field":"未来工作方式","format":"对比分析 + 实操指南","core_concept":"分析爱沙尼亚/葡萄牙/巴厘岛等30国游民签证,结合中国护照限制,给出签证+保险+税务+社群的完整路线","audience_pain":"想地理套利但被签证和社保困扰","unique_angle":"不是简单列出签证,而是给出中国护照持有者的可行组合方案(如泰国+大马+巴厘岛)","priority":"高","priority_score":10,"total_score":51,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"A04","title":"一人公司实验:从创意到营收的365天日志","field":"未来工作方式","format":"实践日志 + 方法论","core_concept":"基于Indie Hackers案例,结合中国孤独创业现状,提供MVP设计、现金流管理、法律合规的一站式指南","audience_pain":"想单干但怕失败、缺启动资金、不懂营销","unique_angle":"真实日志形式,展示完整从0到营收的过程,不美化","priority":"高","priority_score":10,"total_score":50,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"A05","title":"AI时代的技能组合:什么技能值得投入10年?","field":"未来工作方式","format":"趋势分析 + 个人规划","core_concept":"基于WEF未来技能报告,划分4个技能维度(AI强化型、AI无法替代、复合型、过时型),帮中国职场人识别护城河技能","audience_pain":"学什么都不放心,怕投入时间后AI又取代","unique_angle":"将全球宏观报告转化为个人技能地图,提供可视化工具","priority":"中","priority_score":7,"total_score":50,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
- {"id":"B01","title":"城市农业ROI报告:20㎡阳台种菜一年,省了多少钱?","field":"可持续生活系统","format":"数据分析 + 实操指南","core_concept":"对比东京垂直农场与国内空间限制,精选高ROI蔬菜品种,智能设备自动灌溉,给出详细成本核算和品种推荐","audience_pain":"想种但怕麻烦、怕亏本、不知道种什么","unique_angle":"用财务思维算账(投入/产出/时间成本),打破'种菜必须有地'的思维","priority":"高","priority_score":10,"total_score":52,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"B02","title":"零浪费家庭实验:一年只产100L垃圾,可能吗?","field":"可持续生活系统","format":"实践实验 + 方法论","core_concept":"对比瑞典零浪费城市,针对中国垃圾分类困境,提供垃圾追踪表、替代方案数据库、社区互助网络","audience_pain":"想环保但觉得做不到、不知道从哪减","unique_angle":"极限实验(100L/年)+ 可执行步骤(从塑料减量开始),不理想化","priority":"高","priority_score":10,"total_score":51,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"B03","title":"低碳生活账单:用3年省了8万,碳足迹降了60%","field":"可持续生活系统","format":"数据分析 + 案例研究","core_concept":"对比欧洲碳税政策,从交通(电动车+共享)、饮食(植物为主)、消费(二手优先)三个维度,展示真实账单变化","audience_pain":"觉得低碳=更贵,不敢尝试","unique_angle":"用财务数据说话(省8万),打破'环保=烧钱'误解","priority":"高","priority_score":10,"total_score":50,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"B04","title":"循环消费实战:10件物品,用3年省了2万","field":"可持续生活系统","format":"实操指南 + 案例清单","core_concept":"对比法国二手强制法与中国闲鱼文化,提供购买决策树(买新/二手/租)、延长寿命技巧、转卖策略","audience_pain":"想买二手但怕质量差、怕麻烦","unique_angle":"10件物品的具体交易记录和对比(手机、相机、家具等),可复制","priority":"中","priority_score":7,"total_score":50,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
- {"id":"B05","title":"社区菜园指南:如何推动小区5户邻居共建共享","field":"可持续生活系统","format":"方法论 + 实操步骤","core_concept":"对比纽约社区花园政策与中国物业协调难题,提供法律风险(物权)、利益分配机制、技术方案(分区+智能)","audience_pain":"想组织但怕纠纷、不懂法律、协调不了邻居","unique_angle":"从1个友好小区试点开始,成功后复制,降低风险","priority":"高","priority_score":10,"total_score":49,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"C01","title":"第二大脑2.0:用DeepSeek+本地向量库建立私有知识系统","field":"个人知识工厂","format":"技术指南 + 实操案例","core_concept":"对比Obsidian+RAG海外实践,针对国内云服务担忧,提供数据主权、隐私保护、无缝检索、AI问答的本地化方案","audience_pain":"想系统化知识但担心云存储安全,怕复杂","unique_angle":"强调数据主权,从API调用到本地部署的渐进路线","priority":"中","priority_score":7,"total_score":52,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"C02","title":"PKM极简实践:PARA系统在Notion上的落地模板","field":"个人知识工厂","format":"模板分享 + 方法论","core_concept":"将Tiago Forte的PARA体系简化为3个核心文件夹,每周10分钟维护,AI辅助整理,让中国人真正用起来","audience_pain":"学了方法坚持不了,工具复杂难上手","unique_angle":"极简版(4个区)+ 每日5分钟习惯养成,降低门槛","priority":"中","priority_score":7,"total_score":51,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"C03","title":"费曼学习法AI增强:如何让AI帮你'教'懂一个概念","field":"个人知识工厂","format":"方法论 + 实践工具","core_concept":"结合经典费曼技巧与AI工具,三步法(AI简化→自我复述→Gap识别)+ 输出倒逼输入","audience_pain":"学东西记不住,自以为懂了但其实不会","unique_angle":"用AI当'测试官',验证你的理解深度,非被动接受知识","priority":"中","priority_score":7,"total_score":50,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
@@ -21,7 +19,7 @@ topics = [
{"id":"D02","title":"数字排毒月:戒掉微信/抖音后,生活发生了什么","field":"科技人文交叉","format":"实践实验 + 效果分析","core_concept":"对比硅谷禅修热与中国'失联恐惧',采用渐进式戒断(无屏时段)+ 替代活动 + 社交边界管理","audience_pain":"想减少屏幕时间但又怕错过重要信息,自律困难","unique_angle":"真实实验记录(not理论),展示戒断前后的生活变化数据","priority":"中","priority_score":7,"total_score":50,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"D03","title":"银发科技报告:给爸妈装智能设备,学到的5个设计原则","field":"科技人文交叉","format":"设计原则 + 案例","core_concept":"对比日本适老化设计与国产'适老模式'鸡肋,提炼简化选项、物理反馈、容错设计、情感连接的具体方案","audience_pain":"给父母买智能设备但他们不用,功能复杂","unique_angle":"不是推荐产品,而是总结5个设计原则,让读者自己改造设备","priority":"中","priority_score":7,"total_score":49,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
{"id":"D04","title":"儿童数字素养课:10岁儿子的AI启蒙12周","field":"科技人文交叉","format":"教育日志 + 方法论","core_concept":"对比芬兰AI教育与国内家长'禁止接触'心态,通过每周1次'AI家庭时间',培养批判性思维和创造力","audience_pain":"不知如何让孩子正确认识AI,怕沉迷又怕脱节","unique_angle":"真实父子12周项目记录,提供可复制的课程大纲","priority":"中","priority_score":7,"total_score":48,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()},
- {"id":"D05","title":"科技与自然共生:如何用AI让阳台农场更'自然'","field":"科技人文交叉","format":"理念 + 实操方案","core_concept":"对比荷兰智能温室与中国人'回归原始'误区,实现技术隐形化(传感器+提醒)+ 自然反馈闭环 + 人工仪式感","audience_pain":"想用科技但又怕失去'自然感',追求矛盾","unique_angle":"技术与情感连接的平衡方案,AI只做幕后,人工保留仪式","priority":"高","priority_score":10,"total_score":48,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()}
+ {"id":"D06","title":"AI时代的隐私悖论:便利与安全的平衡术","field":"科技人文交叉","format":"趋势分析 + 实用指南","core_concept":"分析AI工具便利性背后个人数据的流向,提供普通用户可操作的数据保护策略","audience_pain":"想用AI又担心隐私,不知道如何保护自己","unique_angle":"不是恐吓式说教,而是给出'能做的10件事'的清单","priority":"中","priority_score":7,"total_score":46,"status":"待处理","cases":[],"source_file":"strategy/全球-本土比较研究与全新内容战略规划-2026-04-15.md","created_at":datetime.datetime.now().isoformat()}
]
with open(OUTPUT_FILE:= '/root/openclaw-workspace/projects/yu-zhi-ran/automation/data/sustainability_topics.json', 'w', encoding='utf-8') as f:
diff --git a/scripts/test_image_gen.py b/scripts/test_image_gen.py
deleted file mode 100644
index 56741f5..0000000
--- a/scripts/test_image_gen.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-"""测试图片生成器"""
-
-import sys
-from pathlib import Path
-
-PROJECT_ROOT = Path(__file__).parent.parent
-sys.path.insert(0, str(PROJECT_ROOT))
-
-from scripts.image_generator import ImageGenerator
-
-def main():
- print("开始测试图片生成...")
- generator = ImageGenerator()
- print(f"输出目录: {generator.output_dir}")
-
- try:
- files = generator.generate_all_placeholders("测试文章标题:上海阳台种菜一年", "zhihu")
- print(f"✅ 成功生成 {len(files)} 张图片:")
- for name, path in files.items():
- size_kb = path.stat().st_size // 1024
- print(f" - {name}: {path.name} ({size_kb}KB)")
- print(f"图片保存在: {generator.output_dir}")
- return 0
- except Exception as e:
- print(f"❌ 生成失败: {e}")
- import traceback
- traceback.print_exc()
- return 1
-
-if __name__ == "__main__":
- sys.exit(main())
\ No newline at end of file