清理城市农业类别 + 修复采集器LLM直接选题
清理: - sustainability_cases.json移除GLO-001/CHN-001城市农业案例,替换为循环消费 - initial_cases.json移除case8东京垂直农场/case26城市屋顶农场 - strategy_topics_to_json.py移除B01/B05/D05三个种菜选题 - collector.py移除城市农业→循环消费映射,更新注释 - 删除fix_collector.py/test_image_gen.py/generate_images.py等遗留脚本 - 删除import_topics.py和automation/下旧版生成脚本 修复: - collector.py _generate_topic_with_llm不再依赖搜索结果,无搜索时LLM直接生成 - run()始终调用LLM,不再要求web_search_results非空 - 替换sources.yaml中已失效的RSS源(澎湃/虎嗅/中新网→36氪/少数派)
This commit is contained in:
@@ -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}")
|
||||
@@ -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 = '<div class="chapter-separator" style="margin: 40px 0 20px; border-top: 2px dashed #e0e0e0;"></div>\n'
|
||||
|
||||
# 找到所有 h2 标题
|
||||
h2_pattern = re.compile(r'(<h2>.*?</h2>)', 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}")
|
||||
@@ -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 最新政策对比",
|
||||
|
||||
@@ -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": "已验证"
|
||||
}
|
||||
]
|
||||
@@ -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}")
|
||||
@@ -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)}")
|
||||
@@ -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'<img src="{path}" alt="{alt}" style="max-width:100%; margin:20px 0; display:block;">'
|
||||
|
||||
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'<h1>{line[2:]}</h1>')
|
||||
elif line.startswith('## '):
|
||||
html_lines.append(f'<h2>{line[3:]}</h2>')
|
||||
elif line.startswith('### '):
|
||||
html_lines.append(f'<h3>{line[4:]}</h3>')
|
||||
elif line.startswith('---'):
|
||||
html_lines.append('<hr style="border:none;border-top:2px dashed #ddd;margin:40px 0;">')
|
||||
elif line.startswith('> '):
|
||||
html_lines.append(f'<blockquote style="border-left:4px solid #4CAF50;background:#f9f9f9;padding:10px 20px;margin:20px 0;color:#666;">{line[2:]}</blockquote>')
|
||||
elif re.match(r'^[-*] ', line):
|
||||
html_lines.append(f'<li>{line[2:]}</li>')
|
||||
elif re.match(r'^\d+\. ', line):
|
||||
html_lines.append(f'<li>{line[line.find(". ")+2:]}</li>')
|
||||
elif line.strip() == '':
|
||||
html_lines.append('<br>')
|
||||
else:
|
||||
# 处理行内粗体斜体
|
||||
tmp = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', line)
|
||||
tmp = re.sub(r'\*(.*?)\*', r'<em>\1</em>', tmp)
|
||||
html_lines.append(f'<p>{tmp}</p>')
|
||||
|
||||
html = f'''<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>上海阳台种菜一年</title>
|
||||
<style>
|
||||
body {{ font-family: "Microsoft YaHei", sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; line-height: 1.8; }}
|
||||
h1 {{ font-size: 28px; border-bottom: 2px solid #4CAF50; padding-bottom: 10px; }}
|
||||
h2 {{ font-size: 24px; margin-top: 40px; border-left: 4px solid #4CAF50; padding-left: 10px; }}
|
||||
h3 {{ font-size: 20px; margin-top: 30px; color: #666; }}
|
||||
img {{ max-width: 100%; height: auto; border-radius: 4px; margin: 20px 0; display: block; margin-left: auto; margin-right: auto; }}
|
||||
blockquote {{ border-left: 4px solid #4CAF50; background: #f9f9f9; padding: 10px 20px; margin: 20px 0; color: #666; }}
|
||||
li {{ margin-bottom: 8px; }}
|
||||
p {{ margin-bottom: 16px; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{chr(10).join(html_lines)}
|
||||
</body>
|
||||
</html>'''
|
||||
|
||||
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 文件夹)")
|
||||
@@ -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'<img src="data:image/png;base64,{image_cache[key]}" alt="{alt}" style="max-width:100%; margin:20px 0; display:block;">'
|
||||
else:
|
||||
return f'<p>[图片缺失: {fname}]</p>'
|
||||
|
||||
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'<h1>{line[2:]}</h1>')
|
||||
elif line.startswith('## '):
|
||||
html_lines.append(f'<h2>{line[3:]}</h2>')
|
||||
elif line.startswith('### '):
|
||||
html_lines.append(f'<h3>{line[4:]}</h3>')
|
||||
elif line.startswith('---'):
|
||||
html_lines.append('<hr>')
|
||||
elif line.startswith('> '):
|
||||
html_lines.append(f'<blockquote>{line[2:]}</blockquote>')
|
||||
elif re.match(r'^[-*] ', line):
|
||||
html_lines.append(f'<li>{line[2:]}</li>')
|
||||
elif re.match(r'^\d+\. ', line):
|
||||
html_lines.append(f'<li>{line[line.find(". ")+2:]}</li>')
|
||||
elif line.strip() == '':
|
||||
html_lines.append('<br>')
|
||||
else:
|
||||
tmp = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', line)
|
||||
tmp = re.sub(r'\*(.*?)\*', r'<em>\1</em>', tmp)
|
||||
html_lines.append(f'<p>{tmp}</p>')
|
||||
|
||||
html = f'''<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>上海阳台种菜一年</title>
|
||||
<style>
|
||||
body {{ font-family: "Microsoft YaHei", sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; line-height: 1.8; }}
|
||||
h1 {{ font-size: 28px; border-bottom: 2px solid #4CAF50; padding-bottom: 10px; }}
|
||||
h2 {{ font-size: 24px; margin-top: 40px; border-left: 4px solid #4CAF50; padding-left: 10px; }}
|
||||
h3 {{ font-size: 20px; margin-top: 30px; color: #666; }}
|
||||
img {{ max-width: 100%; height: auto; border-radius: 4px; margin: 20px 0; display: block; margin-left: auto; margin-right: auto; }}
|
||||
blockquote {{ border-left: 4px solid #4CAF50; background: #f9f9f9; padding: 10px 20px; margin: 20px 0; color: #666; }}
|
||||
li {{ margin-bottom: 8px; }}
|
||||
p {{ margin-bottom: 16px; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
{chr(10).join(html_lines)}
|
||||
</body>
|
||||
</html>'''
|
||||
|
||||
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)} 张")
|
||||
@@ -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(" - 添加免责声明")
|
||||
Reference in New Issue
Block a user