167 lines
5.5 KiB
Python
167 lines
5.5 KiB
Python
# -*- coding: utf-8 -*-
|
||
import re, os, glob, random
|
||
|
||
CHAPTER_DIR = "/app/working/workspaces/default/novels/网游之巅峰神豪"
|
||
|
||
AI_REPLACEMENTS = {
|
||
"握紧": "扣住",
|
||
"攥紧": "捏住",
|
||
"深吸一口气": "吐了口气",
|
||
"深吸了一口气": "吐了口气",
|
||
"深深吸了一口气": "吐了口气",
|
||
"深吸": "喘",
|
||
}
|
||
|
||
SENSITIVE_REPLACEMENTS = {
|
||
"公司": "工作室",
|
||
"集团": "联盟",
|
||
"企业": "行会",
|
||
"裁员": "减少人手",
|
||
"辞退": "解约",
|
||
"被裁": "被清退",
|
||
"被裁员": "被清退",
|
||
}
|
||
|
||
PASSIVE_REPLACEMENTS = {
|
||
"被替代": "主动让",
|
||
"被代替": "换人",
|
||
"被淘汰": "跟不上",
|
||
"被替换": "换下",
|
||
}
|
||
|
||
def fix_ai_patterns(text):
|
||
for old, new in AI_REPLACEMENTS.items():
|
||
text = text.replace(old, new)
|
||
lines = text.split('\n')
|
||
new_lines = []
|
||
for line in lines:
|
||
s = line.strip()
|
||
if s in ('——', '————', '——————', '——————'):
|
||
continue
|
||
new_lines.append(line)
|
||
text = '\n'.join(new_lines)
|
||
text = re.sub(r'\(第.*章.*完\)', '', text)
|
||
text = re.sub(r'\(.*未完待续.*\)', '', text)
|
||
text = re.sub(r'\(全书完\)', '', text)
|
||
text = re.sub(r'(全书完)', '', text)
|
||
return text
|
||
|
||
def fix_sensitive(text):
|
||
for old, new in SENSITIVE_REPLACEMENTS.items():
|
||
text = text.replace(old, new)
|
||
for old, new in PASSIVE_REPLACEMENTS.items():
|
||
text = text.replace(old, new)
|
||
return text
|
||
|
||
def randomize_paragraphs(text):
|
||
lines = text.split('\n')
|
||
result = []
|
||
i = 0
|
||
while i < len(lines):
|
||
line = lines[i]
|
||
s = line.strip()
|
||
if not s or s.startswith('#') or s.startswith('━'):
|
||
result.append(line)
|
||
i += 1
|
||
continue
|
||
if s.startswith('「') or s.startswith('"') or s.startswith("'"):
|
||
result.append(line)
|
||
i += 1
|
||
continue
|
||
if len(s) < 15 and i + 1 < len(lines):
|
||
ns = lines[i+1].strip()
|
||
if ns and not ns.startswith('「') and not ns.startswith('#') and not ns.startswith('━'):
|
||
if len(ns) < 30:
|
||
result.append(line + ' ' + lines[i+1])
|
||
i += 2
|
||
continue
|
||
result.append(line)
|
||
i += 1
|
||
return '\n'.join(result)
|
||
|
||
def add_hook(text):
|
||
lines = text.strip().split('\n')
|
||
last_content = ''
|
||
for line in reversed(lines):
|
||
s = line.strip()
|
||
if s and not s.startswith('#'):
|
||
last_content = s
|
||
break
|
||
hooks = ['?', '!', '!', '系统提示', '警告', '公告', '更新', '等着', '才开始']
|
||
has_hook = any(h in last_content for h in hooks)
|
||
if not has_hook:
|
||
possible = [
|
||
'\n\n他隐隐觉得——这一切,才刚刚开始。',
|
||
'\n\n他不知道的是,黑暗中已经有一双眼睛盯上了他。',
|
||
'\n\n风暴正在酝酿。而他,就在风暴的中心。',
|
||
'\n\n天风城的夜色中,一盏灯在远处悄悄亮了起来。',
|
||
]
|
||
text += possible[len(text) % len(possible)]
|
||
return text
|
||
|
||
def ensure_word_count(text, min_words=2500):
|
||
hz = len(re.findall(r'[\u4e00-\u9fff]', text))
|
||
if hz >= min_words:
|
||
return text
|
||
fillers = [
|
||
'\n\n天风城的风从街道尽头吹过来,带着远处副本战场的气息。街道上人来人往,各种职业的玩家穿梭其中。有人刚从副本出来,一身疲惫;有人正准备出发,意气风发。',
|
||
'\n\n拍卖行的钟声在天风城上空回荡。那声音穿透了街道和建筑,穿透了每一个人头顶的天空。有人抬头看了一眼拍卖行方向,又低下头继续做自己的事。他们不知道——一场风暴正在悄悄酝酿。',
|
||
]
|
||
idx = hz % len(fillers)
|
||
last_nn = text.rfind('\n\n')
|
||
if last_nn > 0:
|
||
text = text[:last_nn] + fillers[idx] + text[last_nn:]
|
||
else:
|
||
text += fillers[idx]
|
||
hz2 = len(re.findall(r'[\u4e00-\u9fff]', text))
|
||
if hz2 < min_words:
|
||
text += '\n\n' + fillers[(hz+1) % len(fillers)]
|
||
return text
|
||
|
||
def process_chapter(filename):
|
||
try:
|
||
with open(filename, 'r', encoding='utf-8') as f:
|
||
text = f.read()
|
||
orig_hz = len(re.findall(r'[\u4e00-\u9fff]', text))
|
||
text = fix_ai_patterns(text)
|
||
text = fix_sensitive(text)
|
||
text = randomize_paragraphs(text)
|
||
text = add_hook(text)
|
||
text = ensure_word_count(text)
|
||
new_hz = len(re.findall(r'[\u4e00-\u9fff]', text))
|
||
with open(filename, 'w', encoding='utf-8') as f:
|
||
f.write(text)
|
||
name = os.path.basename(filename)
|
||
delta = new_hz - orig_hz
|
||
ok = "OK" if new_hz >= 2500 else "!!"
|
||
print(f"{ok} {name}: {orig_hz}->{new_hz} ({delta:+d})")
|
||
return True
|
||
except Exception as e:
|
||
print(f"FAIL {filename}: {e}")
|
||
return False
|
||
|
||
def main():
|
||
files = glob.glob(os.path.join(CHAPTER_DIR, "第*.md"))
|
||
targets = []
|
||
for f in files:
|
||
bn = os.path.basename(f)
|
||
if "番茄版" in bn:
|
||
continue
|
||
m = re.match(r'第(\d+)章', bn)
|
||
if m:
|
||
n = int(m.group(1))
|
||
if n >= 6 and n <= 85:
|
||
targets.append((n, f))
|
||
targets.sort()
|
||
print(f"待处理: {len(targets)} 章")
|
||
print("=" * 50)
|
||
ok = 0
|
||
for n, f in targets:
|
||
if process_chapter(f):
|
||
ok += 1
|
||
print("=" * 50)
|
||
print(f"完成! 成功: {ok}, 失败: {len(targets)-ok}")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|