codebee 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/core/bookmeta.py +161 -27
- package/app/core/bookmeta_catalog.py +187 -0
- package/app/core/builtin_agent.py +382 -0
- package/app/core/flows.py +1 -1
- package/app/core/jobs.py +441 -424
- package/app/core/manager.py +1523 -1511
- package/app/core/market_remote.py +959 -896
- package/app/core/modelhub.py +7 -0
- package/app/core/pipeline.py +138 -32
- package/app/core/store.py +3 -1
- package/app/main.py +1478 -1448
- package/app/ui/app.js +212 -20
- package/app/ui/i18n.js +1732 -1712
- package/app/ui/index.html +6 -2
- package/app/ui/style.css +87 -59
- package/bin/tutti.js +147 -147
- package/package.json +39 -39
package/app/core/bookmeta.py
CHANGED
|
@@ -43,12 +43,15 @@ def needs_book_meta(task):
|
|
|
43
43
|
return True
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
#
|
|
46
|
+
# 各平台建书表单的字段展示顺序(前端卡片与 Markdown 归档共用)。
|
|
47
|
+
# 番茄官方表单:目标读者 → 分类 → 标签(主题/角色/情节 三组多选);
|
|
48
|
+
# 签约模式官方叫法「连载签约/完本签约」。
|
|
47
49
|
FIELD_LABELS = {
|
|
48
50
|
"fanqie": [
|
|
49
51
|
("book_name", "作品名"), ("signing_mode", "签约模式"),
|
|
50
|
-
("target_reader", "目标读者"), ("
|
|
51
|
-
("
|
|
52
|
+
("target_reader", "目标读者"), ("category", "分类"),
|
|
53
|
+
("tags_theme", "主题标签"), ("tags_role", "角色标签"),
|
|
54
|
+
("tags_plot", "情节标签"), ("protagonist_1", "主角名1"),
|
|
52
55
|
("protagonist_2", "主角名2"), ("summary", "作品简介"),
|
|
53
56
|
],
|
|
54
57
|
"qimao": [
|
|
@@ -68,21 +71,59 @@ __SKILLS__
|
|
|
68
71
|
不要输出其他内容。JSON 结构:
|
|
69
72
|
__SCHEMA__
|
|
70
73
|
硬性要求:
|
|
71
|
-
-
|
|
72
|
-
-
|
|
74
|
+
- 字段值必须贴合素材内容,不编造素材里没有的设定;简介不超过 500 字,突出卖点与钩子;
|
|
75
|
+
- __OPTIONS_RULE__
|
|
73
76
|
- 题材健康,无违规内容,符合平台签约调性。
|
|
74
77
|
"""
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
# 签约模式官方叫法(番茄帮助中心):连载签约 / 完本签约
|
|
80
|
+
FANQIE_MODES = ("连载签约", "完本签约")
|
|
81
|
+
|
|
82
|
+
FANQIE_SCHEMA = ('{"book_name": "作品名(15字内)", "signing_mode": "连载签约 或 完本签约", '
|
|
83
|
+
'"target_reader": "男频 或 女频", "category": "分类(从下方分类表选一个)", '
|
|
84
|
+
'"tags_theme": ["主题标签", …最多3个], "tags_role": ["角色标签", …最多3个], '
|
|
85
|
+
'"tags_plot": ["情节标签", …最多5个], '
|
|
86
|
+
'"protagonist_1": "主角名1(5字内)", '
|
|
87
|
+
'"protagonist_2": "主角名2(5字内,没有就空串)", "summary": "作品简介(500字内)"}')
|
|
88
|
+
|
|
89
|
+
QIMAO_SCHEMA = ('{"book_name": "作品名称(15字内)", "target_reader": "男生 或 女生", '
|
|
90
|
+
'"category_main": "一级分类(从下方一级分类表选一个)", '
|
|
91
|
+
'"category_sub": "二级分类(必须是该一级下的二级)", '
|
|
92
|
+
'"tags": ["作品标签", …最多6个,从标签池选], '
|
|
93
|
+
'"protagonist_1": "主角名1(5字内)", '
|
|
84
94
|
'"protagonist_2": "主角名2(5字内,没有就空串)", "status": "连载中 或 已完结", '
|
|
85
|
-
'"summary": "作品简介(
|
|
95
|
+
'"summary": "作品简介(200字内)"}')
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _fq_tables(reader):
|
|
99
|
+
"""番茄按目标读者取对应选项表(男频/女频两套完全独立的分类与标签)。"""
|
|
100
|
+
from . import bookmeta_catalog as cat
|
|
101
|
+
if reader == "女频":
|
|
102
|
+
return (cat.FANQIE_FEMALE_CATEGORIES, cat.FANQIE_FEMALE_TAGS_THEME,
|
|
103
|
+
cat.FANQIE_FEMALE_TAGS_ROLE, cat.FANQIE_FEMALE_TAGS_PLOT)
|
|
104
|
+
return (cat.FANQIE_MALE_CATEGORIES, cat.FANQIE_MALE_TAGS_THEME,
|
|
105
|
+
cat.FANQIE_MALE_TAGS_ROLE, cat.FANQIE_MALE_TAGS_PLOT)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _fq_options_block(goal):
|
|
109
|
+
"""番茄提示词的真实选项注入:按 goal 推断读者给出对应分类与三组标签表。"""
|
|
110
|
+
reader = "女频" if "女" in (goal or "") else "男频"
|
|
111
|
+
cats, theme, role, plot = _fq_tables(reader)
|
|
112
|
+
return ("目标读者(%s)可用的分类表:%s\n"
|
|
113
|
+
"标签分三组多选——主题组:%s\n角色组:%s\n情节组(部分,选最贴合的):%s"
|
|
114
|
+
% (reader, "、".join(cats), "、".join(theme), "、".join(role),
|
|
115
|
+
"、".join(plot[:50])))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _qm_options_block():
|
|
119
|
+
"""七猫提示词的真实选项注入:一级分类 + 已确认级联 + 标签池。"""
|
|
120
|
+
from . import bookmeta_catalog as cat
|
|
121
|
+
cascade = ["%s(二级:%s)" % (k, "、".join(v)) for k, v in cat.QIMAO_CASCADE.items()]
|
|
122
|
+
pool = ["%s组:%s" % (g, "、".join(t)) for g, t in cat.QIMAO_TAG_GROUPS.items()]
|
|
123
|
+
return ("一级分类表:%s\n一级→二级级联(已确认部分,二级必须从所属一级下选):%s\n"
|
|
124
|
+
"标签池(选最贴合的 3-6 个):%s"
|
|
125
|
+
% ("、".join(cat.QIMAO_MAIN_CATEGORIES), ";".join(cascade),
|
|
126
|
+
";".join(pool)))
|
|
86
127
|
|
|
87
128
|
|
|
88
129
|
def _collect_material(task):
|
|
@@ -141,11 +182,34 @@ def _summary(v):
|
|
|
141
182
|
return str(v or "").strip()[:500]
|
|
142
183
|
|
|
143
184
|
|
|
185
|
+
def _in_table(v, table, limit=10):
|
|
186
|
+
"""值必须在平台真实选项表内;不在返回空串(宁缺勿错——填了假选项用户还得手动改)。"""
|
|
187
|
+
s = _name(v, limit)
|
|
188
|
+
return s if s in (table or []) else ""
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _filter_table(v, table, limit=6):
|
|
192
|
+
"""多选标签:只保留表内项(保持模型给的顺序),去重截断。"""
|
|
193
|
+
if not isinstance(v, list):
|
|
194
|
+
return []
|
|
195
|
+
out = []
|
|
196
|
+
for x in v:
|
|
197
|
+
s = str(x).strip()[:12]
|
|
198
|
+
if s and s in (table or []) and s not in out:
|
|
199
|
+
out.append(s)
|
|
200
|
+
if len(out) >= limit:
|
|
201
|
+
break
|
|
202
|
+
return out
|
|
203
|
+
|
|
204
|
+
|
|
144
205
|
def _norm(data, platform, goal=""):
|
|
145
|
-
"""规范化平台字段输出;不合规返回 None。
|
|
206
|
+
"""规范化平台字段输出;不合规返回 None。
|
|
207
|
+
|
|
208
|
+
分类/标签按平台真实选项表校验(bookmeta_catalog):分类单选不在表内清空、
|
|
209
|
+
标签多选只留表内项;七猫二级按级联校验(一级无级联记录时宽松放行)。"""
|
|
146
210
|
if not isinstance(data, dict):
|
|
147
211
|
return None
|
|
148
|
-
book_name = _name(data.get("book_name"), 15 if platform == "fanqie" else
|
|
212
|
+
book_name = _name(data.get("book_name"), 15 if platform == "fanqie" else 15)
|
|
149
213
|
summary = _summary(data.get("summary"))
|
|
150
214
|
if not book_name and not summary:
|
|
151
215
|
return None
|
|
@@ -154,23 +218,34 @@ def _norm(data, platform, goal=""):
|
|
|
154
218
|
if reader not in ("男频", "女频"):
|
|
155
219
|
reader = "女频" if "女" in (goal or "") else "男频"
|
|
156
220
|
mode = str(data.get("signing_mode") or "").strip()
|
|
157
|
-
if mode not in
|
|
158
|
-
mode = "
|
|
221
|
+
if mode not in FANQIE_MODES:
|
|
222
|
+
mode = "连载签约"
|
|
223
|
+
cats, theme, role, plot = _fq_tables(reader)
|
|
224
|
+
# 兼容旧字段:read_tags/content_tags 并入情节/主题组(老数据不丢)
|
|
225
|
+
legacy_read = data.get("read_tags") if isinstance(data.get("read_tags"), list) else []
|
|
159
226
|
return {"book_name": book_name, "signing_mode": mode, "target_reader": reader,
|
|
160
|
-
"
|
|
161
|
-
"
|
|
227
|
+
"category": _in_table(data.get("category"), cats),
|
|
228
|
+
"tags_theme": _filter_table(data.get("tags_theme"), theme),
|
|
229
|
+
"tags_role": _filter_table(data.get("tags_role"), role),
|
|
230
|
+
"tags_plot": _filter_table(data.get("tags_plot"), plot),
|
|
231
|
+
"legacy_read_tags": _filter_table(legacy_read, plot + theme + role),
|
|
162
232
|
"protagonist_1": _name(data.get("protagonist_1"), 5),
|
|
163
233
|
"protagonist_2": _name(data.get("protagonist_2"), 5),
|
|
164
234
|
"summary": summary}
|
|
235
|
+
from . import bookmeta_catalog as cat
|
|
165
236
|
reader = str(data.get("target_reader") or "").strip()
|
|
166
237
|
if reader not in ("男生", "女生"):
|
|
167
238
|
reader = "女生" if "女" in (goal or "") else "男生"
|
|
168
239
|
status = str(data.get("status") or "").strip()
|
|
169
240
|
if status not in ("连载中", "已完结"):
|
|
170
241
|
status = "连载中"
|
|
242
|
+
c_main = _in_table(data.get("category_main"), cat.QIMAO_MAIN_CATEGORIES)
|
|
243
|
+
c_sub = _name(data.get("category_sub"), 10)
|
|
244
|
+
subs = cat.QIMAO_CASCADE.get(c_main)
|
|
245
|
+
if subs and c_sub not in subs:
|
|
246
|
+
c_sub = "" # 级联不匹配清空(二级必须挂在一级下)
|
|
171
247
|
return {"book_name": book_name, "target_reader": reader,
|
|
172
|
-
"category_main":
|
|
173
|
-
"category_sub": _name(data.get("category_sub"), 10),
|
|
248
|
+
"category_main": c_main, "category_sub": c_sub,
|
|
174
249
|
"tags": _tags(data.get("tags")),
|
|
175
250
|
"protagonist_1": _name(data.get("protagonist_1"), 5),
|
|
176
251
|
"protagonist_2": _name(data.get("protagonist_2"), 5),
|
|
@@ -178,13 +253,69 @@ def _norm(data, platform, goal=""):
|
|
|
178
253
|
|
|
179
254
|
|
|
180
255
|
def _template_meta(task, platform, outline):
|
|
181
|
-
"""兜底模板:只做素材搬运归纳(书名/简介来自大纲与目标),其余留空待补。
|
|
256
|
+
"""兜底模板:只做素材搬运归纳(书名/简介来自大纲与目标),其余留空待补。
|
|
257
|
+
|
|
258
|
+
标签/分类尽力而为:扫描素材文本(goal/圣经/大纲书名)里恰好命中平台
|
|
259
|
+
选项表的词就带上——模板没有模型理解力,不做语义归纳,命中多少算多少,
|
|
260
|
+
其余留「待补充」让用户手选(宁缺勿错,不填表外词)。"""
|
|
182
261
|
goal = task.get("goal") or ""
|
|
183
262
|
book_name = str((outline or {}).get("book_title") or task.get("title") or "").strip()
|
|
184
263
|
summary = goal.splitlines()[0][:500] if goal.strip() else ""
|
|
185
264
|
if not summary:
|
|
186
265
|
summary = book_name or "(待补充)" # 全空素材也要有返回,_norm 才不会拒绝
|
|
187
|
-
|
|
266
|
+
material = goal
|
|
267
|
+
try:
|
|
268
|
+
_, bible, _ = store_read_bible(task)
|
|
269
|
+
material += "\n" + (bible or "")
|
|
270
|
+
except Exception:
|
|
271
|
+
pass
|
|
272
|
+
if outline:
|
|
273
|
+
material += "\n" + str(outline.get("book_title") or "")
|
|
274
|
+
data = {"book_name": book_name, "summary": summary}
|
|
275
|
+
if platform == "fanqie":
|
|
276
|
+
reader = "女频" if "女" in goal else "男频"
|
|
277
|
+
cats, theme, role, plot = _fq_tables(reader)
|
|
278
|
+
data.update({"target_reader": reader,
|
|
279
|
+
"category": _scan_table(material, cats, 1),
|
|
280
|
+
"tags_theme": _scan_table(material, theme, 3),
|
|
281
|
+
"tags_role": _scan_table(material, role, 3),
|
|
282
|
+
"tags_plot": _scan_table(material, plot, 5)})
|
|
283
|
+
else:
|
|
284
|
+
from . import bookmeta_catalog as cat
|
|
285
|
+
data["target_reader"] = "女生" if "女" in goal else "男生"
|
|
286
|
+
for main, subs in cat.QIMAO_CASCADE.items():
|
|
287
|
+
if main in material:
|
|
288
|
+
data["category_main"] = main
|
|
289
|
+
for s in subs: # 二级名撞素材即选(如「宫闱宅斗」)
|
|
290
|
+
if s in material:
|
|
291
|
+
data["category_sub"] = s
|
|
292
|
+
break
|
|
293
|
+
break
|
|
294
|
+
pool = [t for ts in cat.QIMAO_TAG_GROUPS.values() for t in ts]
|
|
295
|
+
data["tags"] = _scan_table(material, pool, 6)
|
|
296
|
+
return _norm(data, platform, goal)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _scan_table(text, table, limit):
|
|
300
|
+
"""素材文本里命中的选项表词(按表序取,保证真实存在)。"""
|
|
301
|
+
if not text:
|
|
302
|
+
return []
|
|
303
|
+
out = []
|
|
304
|
+
for word in table:
|
|
305
|
+
if len(word) >= 2 and word in text:
|
|
306
|
+
out.append(word)
|
|
307
|
+
if len(out) >= limit:
|
|
308
|
+
break
|
|
309
|
+
return out
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def store_read_bible(task):
|
|
313
|
+
"""圣经读取的小包装(模板兜底用;异常向上抛由调用方吞掉)。"""
|
|
314
|
+
from . import store
|
|
315
|
+
fp, text, err = store.read_story_bible(task.get("id") or "")
|
|
316
|
+
if err:
|
|
317
|
+
raise ValueError(err)
|
|
318
|
+
return fp, text, None
|
|
188
319
|
|
|
189
320
|
|
|
190
321
|
def _resolve_author(task):
|
|
@@ -206,10 +337,13 @@ def make_book_meta(task, platform, author_agent=None, log_path=None):
|
|
|
206
337
|
schema = {"fanqie": FANQIE_SCHEMA, "qimao": QIMAO_SCHEMA}.get(platform) or ""
|
|
207
338
|
plat_label = PLATFORMS[platform]["label"]
|
|
208
339
|
sk_block, _ = skills.block_for(task)
|
|
340
|
+
goal = task.get("goal") or ""
|
|
341
|
+
# 真实选项注入:分类/标签表按平台与读者频段给全(模型只能从表里选)
|
|
342
|
+
options = (_fq_options_block(goal) if platform == "fanqie" else _qm_options_block())
|
|
209
343
|
prompt = (PROMPT_HEAD.replace("__PLATFORM__", plat_label)
|
|
210
344
|
.replace("__SKILLS__", sk_block)
|
|
211
|
-
.replace("__SCHEMA__", schema)
|
|
212
|
-
|
|
345
|
+
.replace("__SCHEMA__", schema)
|
|
346
|
+
.replace("__OPTIONS_RULE__", options) + "\n\n## 小说素材\n" + material)
|
|
213
347
|
|
|
214
348
|
orch = None
|
|
215
349
|
if not template_only():
|
|
@@ -264,7 +398,7 @@ def render_markdown(task, platform, meta):
|
|
|
264
398
|
v = str(v or "").strip() or "(待补充)"
|
|
265
399
|
lines.append("- **%s**:%s" % (label, v))
|
|
266
400
|
lines.append("")
|
|
267
|
-
lines.append("> 各字段可直接复制进 %s
|
|
401
|
+
lines.append("> 各字段可直接复制进 %s 建书表单;分类与标签均选自平台真实选项表。" % plat)
|
|
268
402
|
return "\n".join(lines)
|
|
269
403
|
|
|
270
404
|
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""建书表单的真实选项目录:番茄官方 API 实抓 + 七猫官网书库页实抓。
|
|
3
|
+
|
|
4
|
+
数据来源(2026-09-16 抓取):
|
|
5
|
+
- 番茄:https://fanqienovel.com/api/author/book/category_list/v0/?gender=1|0
|
|
6
|
+
(官方接口,无需登录;主分类 + 主题/角色/情节 三组标签,按目标读者分两套)
|
|
7
|
+
- 七猫:官网书库 SSR 页 + 榜单 API 的 category1/category2 真实配对;标签池来自
|
|
8
|
+
作者专区标签系统快照(GitHub Lorn.NovelWriteSkills,2026-06,四组:风格/角色/
|
|
9
|
+
情节/背景)。级联表未覆盖的一级分类(出版类等非主赛道)二级宽松放行。
|
|
10
|
+
|
|
11
|
+
改这些表不影响已保存任务(book_meta 生成时快照)。
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
# 番茄·男频主分类(gender=1)
|
|
15
|
+
FANQIE_MALE_CATEGORIES = [
|
|
16
|
+
"西方奇幻", "东方仙侠", "科幻末世", "男频衍生", "都市高武", "悬疑灵异",
|
|
17
|
+
"悬疑脑洞", "抗战谍战", "历史古代", "历史脑洞", "都市种田", "都市脑洞",
|
|
18
|
+
"都市日常", "玄幻脑洞", "战神赘婿", "动漫衍生", "游戏体育", "传统玄幻",
|
|
19
|
+
"都市修真",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
# 番茄·男频标签-主题组
|
|
23
|
+
FANQIE_MALE_TAGS_THEME = [
|
|
24
|
+
"衍生", "仕途", "综影视", "天灾", "第一人称", "赛博朋克",
|
|
25
|
+
"第四天灾", "规则怪谈", "搞笑轻松", "古代", "悬疑", "克苏鲁",
|
|
26
|
+
"都市异能", "末日求生", "灵气复苏", "高武世界", "异世大陆", "东方玄幻",
|
|
27
|
+
"谍战", "清朝", "宋朝", "断层", "武将", "国运",
|
|
28
|
+
"综漫", "开局", "架空", "奇幻仙侠", "都市", "玄幻",
|
|
29
|
+
"历史", "体育", "武侠",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
# 番茄·男频标签-角色组
|
|
33
|
+
FANQIE_MALE_TAGS_ROLE = [
|
|
34
|
+
"多女主", "赘婿", "全能", "大佬", "大小姐", "特工",
|
|
35
|
+
"游戏主播", "神探", "贵族", "皇帝", "单女主", "校花",
|
|
36
|
+
"无女主", "女帝", "特种兵", "反派", "神医", "奶爸",
|
|
37
|
+
"学霸", "天才", "腹黑", "扮猪吃虎",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
# 番茄·男频标签-情节组
|
|
41
|
+
FANQIE_MALE_TAGS_PLOT = [
|
|
42
|
+
"都市江湖", "风水秘术", "斩神衍生", "十日衍生", "西游衍生", "公版衍生",
|
|
43
|
+
"红楼衍生", "甄嬛衍生", "如懿衍生", "惊悚游戏", "卡牌", "山海经",
|
|
44
|
+
"捉鬼", "剑修", "废土", "副本", "黑科技", "无脑爽",
|
|
45
|
+
"魂穿", "高手下山", "黑化", "迪化", "发家致富", "无后宫",
|
|
46
|
+
"争霸", "1v1", "升级流", "灵魂互换", "科举", "封神",
|
|
47
|
+
"四合院", "电竞", "双重生", "乡村", "同人", "打脸",
|
|
48
|
+
"破案", "囤物资", "钓鱼", "网游", "奥特同人", "求生",
|
|
49
|
+
"无敌", "民国", "九叔", "穿书", "聊天群", "大秦",
|
|
50
|
+
"龙珠", "漫威", "神奇宝贝", "海贼", "火影", "职场",
|
|
51
|
+
"明朝", "家庭", "三国", "末世", "直播", "无限流",
|
|
52
|
+
"诸天万界", "大唐", "宠物", "外卖", "星际", "美食",
|
|
53
|
+
"剑道", "盗墓", "灵异", "鉴宝", "系统", "神豪",
|
|
54
|
+
"重生", "穿越", "二次元", "海岛", "娱乐圈", "空间",
|
|
55
|
+
"推理", "洪荒",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
# 番茄·女频主分类(gender=0)
|
|
59
|
+
FANQIE_FEMALE_CATEGORIES = [
|
|
60
|
+
"女频悬疑", "古风世情", "科幻末世", "女频衍生", "民国言情", "悬疑脑洞",
|
|
61
|
+
"青春甜宠", "双男主", "古言脑洞", "现言脑洞", "玄幻言情", "宫斗宅斗",
|
|
62
|
+
"豪门总裁", "动漫衍生", "星光璀璨", "游戏体育", "职场婚恋", "双女主",
|
|
63
|
+
"年代", "种田", "快穿",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
# 番茄·女频标签-主题组
|
|
67
|
+
FANQIE_FEMALE_TAGS_THEME = [
|
|
68
|
+
"古言权谋", "悬疑恋爱", "纯爱", "衍生", "仕途", "综影视",
|
|
69
|
+
"天灾", "第一人称", "赛博朋克", "规则怪谈", "搞笑轻松", "古代",
|
|
70
|
+
"悬疑", "谍战", "职场商战", "虐恋情深", "日久生情", "豪门世家",
|
|
71
|
+
"综漫", "异世穿越", "独宠", "现代言情", "古代言情", "武侠",
|
|
72
|
+
"幻想言情",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
# 番茄·女频标签-角色组
|
|
76
|
+
FANQIE_FEMALE_TAGS_ROLE = [
|
|
77
|
+
"位尊权重", "总裁", "忠犬", "全能", "白切黑", "双学霸",
|
|
78
|
+
"作精", "大佬", "大小姐", "游戏主播", "神探", "贵族",
|
|
79
|
+
"将军", "毒医", "厨娘", "律师", "医生", "明星",
|
|
80
|
+
"替身", "双面", "冰山", "古灵精怪", "天作之合", "可盐可甜",
|
|
81
|
+
"无CP", "病娇", "反派", "萌宝", "宠妻", "学霸",
|
|
82
|
+
"公主", "皇后", "王妃", "女强", "皇叔", "嫡女",
|
|
83
|
+
"精灵", "天才", "腹黑", "扮猪吃虎", "团宠",
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
# 番茄·女频标签-情节组
|
|
87
|
+
FANQIE_FEMALE_TAGS_PLOT = [
|
|
88
|
+
"男二上位", "代嫁代娶", "攻略反派", "风水秘术", "斩神衍生", "十日衍生",
|
|
89
|
+
"西游衍生", "公版衍生", "红楼衍生", "甄嬛衍生", "如懿衍生", "惊悚游戏",
|
|
90
|
+
"追夫", "山海经", "胎穿", "捉鬼", "剑修", "相互救赎",
|
|
91
|
+
"宠夫", "无脑爽", "魂穿", "黑化", "养崽", "年龄差",
|
|
92
|
+
"真假千金", "久别重逢", "发家致富", "养成", "互宠", "1v1",
|
|
93
|
+
"灵魂互换", "科举", "年下", "婚恋", "封神", "四合院",
|
|
94
|
+
"电竞", "双重生", "前世今生", "双洁", "追妻火葬场", "乡村",
|
|
95
|
+
"逃荒", "同人", "打脸", "破案", "囤物资", "钓鱼",
|
|
96
|
+
"HE", "相爱相杀", "暗恋", "逃婚", "带球跑", "强强",
|
|
97
|
+
"一见钟情", "双向奔赴", "破镜重圆", "契约婚姻", "隐婚", "闪婚",
|
|
98
|
+
"今穿古", "古穿今", "群穿", "护短", "虐渣", "情有独钟",
|
|
99
|
+
"马甲", "先婚后爱", "医术", "女扮男装", "青梅竹马", "无敌",
|
|
100
|
+
"民国", "穿书", "职场", "家庭", "末世", "直播",
|
|
101
|
+
"无限流", "兽世", "清穿", "星际", "美食", "盗墓",
|
|
102
|
+
"虐文", "甜宠", "灵异", "校园", "系统", "重生",
|
|
103
|
+
"穿越", "二次元", "娱乐圈", "空间", "推理",
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
# 七猫·一级分类(官网书库筛选栏,23 个)
|
|
107
|
+
QIMAO_MAIN_CATEGORIES = [
|
|
108
|
+
"现代言情", "古代言情", "幻想言情", "历史", "军事", "科幻",
|
|
109
|
+
"游戏", "游戏竞技", "玄幻奇幻", "都市", "奇闻异事", "武侠仙侠",
|
|
110
|
+
"体育", "N次元", "文学艺术", "人文社科", "经管励志", "经典文学",
|
|
111
|
+
"出版小说", "少儿教育", "衍生言情", "现实题材", "现实主义",
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
# 七猫·一级→二级级联(已确认部分;未列出的二级宽松放行)
|
|
115
|
+
QIMAO_CASCADE = {
|
|
116
|
+
"现代言情": [
|
|
117
|
+
"总裁豪门", "职场情缘", "民国旧影", "娱乐明星", "现实生活", "青春校园",
|
|
118
|
+
"年代重生", "都市奇幻", "现代悬疑",
|
|
119
|
+
],
|
|
120
|
+
"古代言情": [
|
|
121
|
+
"种田经商", "宫闱宅斗", "古代情缘", "权谋天下", "武侠江湖", "远古大陆",
|
|
122
|
+
"古代悬疑",
|
|
123
|
+
],
|
|
124
|
+
"幻想言情": [
|
|
125
|
+
"玄幻仙侠", "未来科幻", "无限快穿", "末世求生", "异世幻想",
|
|
126
|
+
],
|
|
127
|
+
"都市": [
|
|
128
|
+
"明星娱乐", "乡村生活", "都市高武", "都市高手", "商战职场", "热血校园",
|
|
129
|
+
"都市生活", "灵气复苏", "官场",
|
|
130
|
+
],
|
|
131
|
+
"玄幻奇幻": [
|
|
132
|
+
"东方玄幻", "异世大陆", "西方奇幻", "诸天万界", "王朝争霸",
|
|
133
|
+
],
|
|
134
|
+
"奇闻异事": [
|
|
135
|
+
"侦探推理", "恐怖灵异", "寻宝探险", "奇门秘术",
|
|
136
|
+
],
|
|
137
|
+
"武侠仙侠": [
|
|
138
|
+
"上古洪荒", "古典仙侠", "传统武侠", "幻想修真", "武侠幻想",
|
|
139
|
+
],
|
|
140
|
+
"军事": [
|
|
141
|
+
"现代军事", "抗战烽火", "谍战特工", "战争幻想",
|
|
142
|
+
],
|
|
143
|
+
"科幻": [
|
|
144
|
+
"星际机甲", "末世危机", "未来幻想",
|
|
145
|
+
],
|
|
146
|
+
"游戏": [
|
|
147
|
+
"电子竞技", "虚拟网游",
|
|
148
|
+
],
|
|
149
|
+
"游戏竞技": [
|
|
150
|
+
"网游电竞", "运动竞技",
|
|
151
|
+
],
|
|
152
|
+
"体育": [
|
|
153
|
+
"其他竞技", "篮球风云", "足球天下",
|
|
154
|
+
],
|
|
155
|
+
"N次元": [
|
|
156
|
+
"原生幻想", "衍生同人", "轻小说",
|
|
157
|
+
],
|
|
158
|
+
"历史": [
|
|
159
|
+
"架空历史",
|
|
160
|
+
],
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# 七猫·作品标签池(四组,作者专区快照常用子集;校验宽松:池外不拒)
|
|
164
|
+
QIMAO_TAG_GROUPS = {
|
|
165
|
+
"风格": [
|
|
166
|
+
"热血", "轻松", "爽文", "甜宠", "虐恋", "悬疑",
|
|
167
|
+
"快节奏", "反套路", "第一人称", "种田", "权谋", "宫斗",
|
|
168
|
+
"宅斗", "美食", "经营", "克苏鲁", "规则怪谈", "无CP",
|
|
169
|
+
],
|
|
170
|
+
"角色": [
|
|
171
|
+
"战神", "赘婿", "神医", "神豪", "奶爸", "女帝",
|
|
172
|
+
"嫡女", "真千金", "大女主", "兵王", "医生", "主播",
|
|
173
|
+
"总裁", "大佬", "学霸", "团宠", "萌宝", "反派",
|
|
174
|
+
],
|
|
175
|
+
"情节": [
|
|
176
|
+
"系统", "金手指", "签到", "御兽", "重生", "穿越",
|
|
177
|
+
"穿书", "快穿", "逆袭", "开局流", "无敌流", "先婚后爱",
|
|
178
|
+
"追妻火葬场", "破镜重圆", "闪婚", "打脸虐渣", "马甲", "养成",
|
|
179
|
+
],
|
|
180
|
+
"背景": [
|
|
181
|
+
"末世", "无限流", "玄学", "盗墓", "鉴宝", "娱乐圈",
|
|
182
|
+
"电竞", "官场", "架空历史", "三国", "大唐", "大明",
|
|
183
|
+
"大秦", "年代", "民国", "高武", "灵气复苏", "诸天万界",
|
|
184
|
+
"科幻", "赛博朋克", "校园", "都市", "乡村", "海岛",
|
|
185
|
+
"星际", "玄幻", "武侠", "仙侠",
|
|
186
|
+
],
|
|
187
|
+
}
|