用 Python 自己写一套建站系统,多数人是被需求逼出来的:现成的 CMS 用着用着发现内容层的规则改不动,模板想按站点细分要动核心代码,AI 生成的内容接不进去,只能靠插件一层层包,包到后来没人敢升级。于是转向自研,Flask 往往是第一选择,体量轻、上手快、生态够用。但真正把源码写出来、站跑起来之后,问题会集中冒出来:站点一多内容互相污染、AI 接口一调就把进程卡住、模板改一处崩三个站。
这些问题的根源基本都指向同一件事:源码的层次没有在动手之前切清楚。路由、模板、数据、内容生成这四层怎么划,直接决定这套系统后面是越用越顺,还是每加一个站都要回头改架构。两条路先摆在一起看。
自己写一套 Flask 源码
- 内容层、发布流程、推送节奏都按自己的业务定义,不受插件边界限制;
- 多站隔离、模板体系、AI 接入可以做成一套底座,新站复制成本低;
- 代价是前期投入和长期维护都要有人扛,出故障没人兜底;
- 适合有稳定开发人力、站点数量上得快的团队。
用现成系统搭底座
- 上线快,发布、备份、权限、推送这些通用能力现成;
- 生态成熟,遇到问题有资料可查、有人维护;
- 定制要顺着系统的规则走,深层需求容易撞天花板;
- 适合人力有限、先把业务跑起来再说的团队。
一、先算清楚自研这笔账,再决定写不写第一行代码
自研从来不是技术问题,是成本问题。一套能稳定跑几十个站点的 Flask 系统,功能上至少要覆盖:多站点配置、内容生成与审核、模板体系、发布与推送、数据看板、故障恢复。这些能力每一个单独做都不难,难的是全部做出来还要经常维护。开工之前,把三条路子放在同一张表里对比,比拍脑袋决定靠谱得多。
| 对比项 | Flask 自研 | 现成 CMS 改造 | 通用建站平台 |
|---|---|---|---|
| 多站管理 | 可做成一套底座无限复制,隔离颗粒度自己定 | 靠多站点插件或分库分表,改造余地有限 | 平台内建站群功能,隔离程度受平台约束 |
| 内容层 | 生成、审核、发布流程按业务自定义 | 按 CMS 的内容模型走,字段改动依赖插件生态 | 使用平台提供的编辑器与发布流程 |
| AI 接入 | 任务队列、模型路由、成本控制自行设计 | 依赖现成插件,能力与稳定性看维护者 | 平台内置 AI 写作,可调参数有限 |
| 维护成本 | 人力自担,安全更新、依赖升级都要盯 | 官方与社区分担一部分,升级有风险窗口 | 平台负责运维,遇到问题走工单 |
(对比维度综合 Flask 社区工程实践与主流 CMS 公开文档整理,具体选型以团队实际人力与业务节奏为准。)
有一种中间状态值得单独说:业务已经跑起来、站点数量在增长,但团队没有精力长期养一套自研源码。这时候更实际的选择是换成把多站隔离、内容中台、发布推送做成现成能力的架站底座,比如用 UC 建站系统这类底座,独立部署、独立模板、多站统一监控都是平台自带,省下的是从零写这些轮子的时间。自研适合把系统当核心资产的团队,其余情况先算时间账。
二、目录结构先定死,后面能少一半返工
Flask 的"微框架"定位意味着它不替你做任何结构决定,这既是自由也是第一道坎。单文件 app.py 的写法只适合演示,站点一多必然失控。工程上比较稳的组织方式是用应用工厂创建实例、用蓝图切业务模块、配置与代码物理分离,落到目录就是这样的骨架:
project/├── app/│ ├── __init__.py # create_app() 应用工厂,注册扩展与蓝图│ ├── models/ # 站点、内容、任务的数据模型│ ├── sites/ # 站点配置包,一个站一份配置│ ├── views/ # 蓝图:前台 / 后台 / 接口分开│ ├── services/ # 业务层:内容生成、审核、发布、推送│ ├── tasks/ # 队列任务:调模型、生成 sitemap、提交链接│ ├── templates/ # 按站点主题分组存放│ └── static/├── config.py # 分环境配置,密钥走环境变量├── migrations/ # 数据库迁移脚本├── requirements.txt└── wsgi.py # 生产入口,交给 Gunicorn 起进程这套骨架里有四个决定后面维护体验的划分原则,动手前值得逐条确认:
- 站点配置外置成数据,不做进代码。新增站点时只加配置、不改逻辑,是整套系统能不能批量复制的分水岭;
- 内容生成独立成服务层,路由只负责收参数、排队、返回任务号,视图函数里不出现模型调用;
- 模板按站点主题分目录,公共组件抽出来共享,避免一套模板复制二十份、改一处漏十九处;
- 数据库迁移从第一天就用起来,手工改表结构在站点数量上去之后是灾难源头。
开源生态里已有基于 Flask 的轻量 CMS 可以参考(比如支持多主题模板、栏目级模板选择的 ZhyCMS 这类项目),但拿它们当骨架前先看维护状态和许可证,参考结构思路比直接 fork 一个年久失修的项目更划算。

三、多站隔离的四个层面,缺一层就出事
一套源码跑多个站,本质上是在同一个进程里服务不同的业务边界。隔离做得干净,站点之间互不打扰;做得潦草,常见的事故包括:A 站的模板渲染了 B 站的数据、某个站被入侵后全站数据泄露、一个站的配置错误拖垮所有站。Flask 里落地隔离的入口是请求钩子,按访问域名绑定站点上下文,后面的取数、渲染、推送都从这个上下文里走:
# app/sites/loader.py 站点上下文绑定(示意)SITE_CONFIG = {"site-a.com": {"theme": "news", "db": "site_a"},"site-b.com": {"theme": "local", "db": "site_b"},}@app.before_requestdef bind_site():host = request.host.split(":")[0]g.site = SITE_CONFIG.get(host)if g.site is None:abort(404) # 未登记域名直接拒绝,防止串站绑定了上下文只是第一步,真正决定稳定性的是隔离做到了哪个颗粒度。四个层面里,前两个做浅一点影响有限,后两个做浅了出事就是连锁的:
| 层面 | 稳妥做法 | 做浅的后果 |
|---|---|---|
| 域名与配置 | 站点配置独立成数据表或配置文件,绑定关系可查可改 | 新增站要改代码、发版本,出错难回滚 |
| 模板层 | 按站点主题分目录,公共组件抽离共享 | 多站模板同构,样式与结构一眼看出是同一批 |
| 数据层 | 分库或按站点字段做强隔离,查询强制带上站点条件 | 跨站数据串号,出现内容错发、统计失真 |
| 内容层 | 生成规则按站点分配角度与素材,产出各有侧重 | 一批文章铺满所有站,同质内容拖累整批收录 |
隔离不是防人,是防自己手滑。数据层最容易被省事的心跳过:一个库、一张内容表,靠 site_id 字段区分,看起来简单,但只要有一次查询忘了带条件,A 站的列表页就会混进 B 站的文章。查询条件收敛到统一的取数入口里,别散落在各个视图函数中,是成本最低的保险。
四、AI 内容层接在哪,才不会拖垮整站
自研系统里最常见的一个翻车点,是把模型调用直接写进视图函数:用户在后台点"生成",请求就一直挂着等模型返回,一篇文章动辄几十秒,同时来三个请求就把进程占满,Nginx 超时、整站卡顿接连出现。Flask 默认是同步阻塞的模型,这类耗时操作必须挪出请求周期,交给队列在后台跑,视图只负责入队和返回任务号:
# app/views/api.py 生成接口:只入队,不等待结果@api.post("/generate")def generate():task = queue.enqueue("services.generator.run",site=request.json["site"],topic=request.json["topic"],job_timeout="10m", # 单篇生成的时间上限)return {"task_id": task.id, "status": "queued"}队列选型上,功能要求高就用 Celery 加 Redis,想省事就用轻量的 RQ,两者都能把任务从请求里剥出去,配套的任务状态查询接口记得一起做,否则后台点完生成,人就只能干等着不知道进度。内容落库之后走一条明确的状态线:草稿、待审、发布,三态各管一段,审核环节留住,批量生产时才不会把关不住。
AI 生成的内容,能不能跳过审核直接发布?
不建议。模型输出存在事实漂移和格式跑偏的可能,涉及医疗、金融、法律这类领域时问题更严重,内容合规责任在站点主体身上,不因为产出来自模型而转移。把审核做成发布链路里的必经节点,批量生产才有可控性;审核人力有限的话,至少保证抽检和技术校验(敏感词、事实核查、格式检查)两道都有。
内容层还欠三件事:调用限流(并发数受模型服务配额约束)、失败重试(网络抖动需要自动补跑而不是人工发现)、成本记录(按站点和任务记每次消耗,月底才有账可算)。这三件事做进任务层,比事后翻日志补要省心。
五、模板直出和 sitemap,自研系统天生占优的地方
框架选型阶段容易被忽略的一点是渲染方式带来的差别。Jinja 模板在服务端渲染成完整 HTML 再返回,页面内容不依赖浏览器执行脚本,抓取和首屏都受益;相比前端整站动态渲染的架构,这类页面在爬虫侧的稳定性更好,这也是 Flask 做内容站的天然优势。配合几件小事,一套自研系统在这块基本不需要额外投入:
sitemap 动态生成
内容发布后在任务里更新地图文件,或用一个路由实时输出,搜索引擎来取时永远是最新的。Flask 生态里有现成的 sitemap 扩展,几行代码就能接上,站点数量多时按站拆分成独立地图更利于排查。
结构化数据与元信息
标题、摘要、面包屑这些字段在设计内容模型时就落到数据结构里,模板里统一输出,别等到页面做完了再回头补标签,散落的模板改起来是重复劳动。
缓存与响应速度
文章页做整页缓存或片段缓存,数据库压力立刻下来;蜘蛛抓取时响应稳定,抓取频次也不容易被下调。缓存失效逻辑挂到发布动作上,改完即更新。
自研最容易被浪费掉的优势就是模板体系:明明可以给每个站配一套结构不同的主题,结果图省事全套用同一份模板,多站之间除了域名和标题不同,页面骨骼一模一样。前面章节反复提的多站同质问题,落到代码上就是模板目录的划分方式,一个目录一个主题,这件事在写第一版的时候就该留好位置。
六、源码是自己的,红线还是那条红线
自研系统的自主权很高,也正因为高,容易在需求压力下一点点滑向危险区:为了内容量接采集接口,为了"新站快速起步"装蜘蛛池类的抓取模拟模块,为了收录加外链买卖插件。这些做法在代码层面只是几个函数,在站点层面却直接触碰搜索引擎的打击清单,代价是索引批量掉落和长期降权。技术上的自由,不等于行为上的豁免。
不接采集与伪原创流水线,不碰蜘蛛池、劫持、外链买卖类模块,这是自研系统的三条硬边界。另外别忘了基础门槛:站点要完成备案,内容要符合法律法规,医疗、金融这类领域需要相应资质,资质不是代码能解决的问题。
用 Flask 自己写系统管多个站,这件事本身有问题吗?
工具本身中性,多站点管理是很多正规业务的需求:集团官网群、区域分站、多语言版本、产品线与品牌矩阵,都在这个范围内。判断标准不在代码,而在内容来源是否合法、质量是否达标、资质是否齐全、行为是否越过搜索规则。把这四条守住,自研系统就是正常的工程实践。
从投入回报的角度看,守规矩也是更划算的路:合规内容能被长期收录、持续带量,作弊手段的收益窗口越来越短,整改成本却越来越高。源码写出来是要长期跑的,别在第一版里埋下需要推倒重来的东西。
七、从零到能跑,按这四步推进不会乱
自研项目失控,多数时候不是技术难度造成的,是顺序错了:单站还没跑稳就开始堆多站功能,内容层还在调试就急着接推送,问题纠缠在一起,排查时分不清是谁的错。把节奏拉开,每步只解决一类问题,验收之后再进下一步:
目录骨架、路由、模板、数据库迁移先在一个站上跑顺,页面能出、后台能改、数据能存
接上队列与状态机,生成任务后台跑通,审核环节走通,一篇内容从选题到发布全流程无人工搬数据
站点配置外置、模板主题分目录、数据隔离加约束,复制第二个站时只加配置不改代码
收录数据进看板、sitemap 定时更新、发布动作带提交任务,异常有提醒而不是靠人巡检
四步走完,这套源码才算能承担多站运营。如果到"多站隔离"这一步发现团队没有精力长期维护,及时改道也是理性选择:把通用能力交给成品底座,自己只保留内容与策略层。UC 建站系统就是按这个思路做的,WP 底层加 AI 管理层,独立部署、独立模板、多站统一看板出厂即带,前面几章里那套"配置外置、模板分组、发布带提交"的架构,在成品系统里不需要自己再实现一遍。
自研源码的价值在于把业务规则沉淀成自己的资产,前提是层次切干净、顺序走对、边界守住。具备这三点的系统,站点数量从十个涨到五十个时是加配置;缺任何一点,就是推倒重来。
动手之前,这套源码值得过的自检清单列在末尾,写代码之前逐条对照一遍,比写完之后再回头调整要便宜得多:
新增站点是否需要改逻辑、发版本,是判断架构成色的第一个问题
模型调用、批量生成、文件处理这类操作,一个都不该出现在请求周期内
多站共用一份模板、查询不强制带站点条件,这两件事在站点变多后都会变成事故
草稿、待审、发布三态清晰,批量内容才控得住质量与合规
sitemap 更新、链接提交、收录监控三个动作是否自动衔接,决定内容产出能不能转化成流量
收尾提醒一句:源码是工具,跑在它上面的内容才是资产。系统写得再漂亮,内容浅、审核松、边界不清,多站也只是多个空壳;反过来,层次干净的源码能把合规内容的生产效率放大若干倍,这才是自研这套东西真正值钱的地方。
(文中工程结构、队列选型与扩展用法整理自 Flask 官方文档及社区实践资料;开源项目仅作结构参考示例,采用前请核对维护状态与许可证。系统搭建与运营需遵守备案、资质与内容合规相关要求。)
