Explorar o código

优化章节内容拆分的正则匹配规则,并写入公共方法以供调用

lh hai 20 horas
pai
achega
dfa5f27302
Modificáronse 2 ficheiros con 99 adicións e 17 borrados
  1. 73 1
      app/Libs/Helpers.php
  2. 26 16
      app/Services/DeepSeek/DeepSeekService.php

+ 73 - 1
app/Libs/Helpers.php

@@ -4337,7 +4337,7 @@ function parseRolesFromText(string $rolesText): array
 }
 
 /**
- * 将场景列表文本拆分为主体数组
+ * 将场景列表文本拆分为场景数组
  * 
  * @param string $rolesText 场景列表列表文本内容
  * @return array 场景名称数组
@@ -4448,6 +4448,78 @@ function parsePropsFromText(string $propsText): array
     return $props;
 }
 
+// 拆分章节内容
+function splitContent($content) {
+    // 根据章节标题来拆分章节内容,返回包含标题和内容的二维数组
+    $chapters = [];
+    
+    // 匹配章节标题格式:
+    // 1. 标题可能独占一行,也可能在正文末尾或中间
+    // 2. 格式支持:
+    //    - **第一集**
+    //    - 第一集:
+    //    - ###第1章 重生
+    //    - ##第2章 相救
+    //    - 第三章 共处一室
+    // 3. 支持阿拉伯数字(0-9)和中文数字(一二两三四五六七八九十百千万)
+    // 4. 支持章节关键字:章、节、集、幕、场、回、话
+    // 5. "第"字与数字、数字与章节关键字之间可能有空格
+    // 6. 前后可能有#、*、·等修饰符号,后面可能有冒号、空格、标题文字等
+    
+    // 先预处理:将标题前后添加换行符,确保标题能被正确识别和拆分
+    // 匹配模式:可能有前缀符号 + "第" + 空格(可选) + 数字 + 空格(可选) + 章节关键字 + 可能的标题内容
+    $pattern = '/([#*·\-_=\s]*)第\s*([一二两三四五六七八九十百千万0-9]+)\s*([章节集幕场话])([^第\n]*?)(?=第\s*[一二两三四五六七八九十百千万0-9]+\s*[章节集幕场话]|$)/u';
+    
+    // 先在每个标题前插入换行符(如果前面不是换行的话)
+    $content = preg_replace('/([^\n])([#*·\-_=\s]*)第\s*([一二两三四五六七八九十百千万0-9]+)\s*([章节集幕场话])/u', "$1\n\n$2第$3$4", $content);
+    
+    // 现在用修改后的模式匹配(标题应该在行首或接近行首)
+    $pattern = '/^[#*·\s\-_=]*第\s*([一二两三四五六七八九十百千万0-9]+)\s*([章节集幕场话]).*$/mu';
+    
+    // 用正则找出所有章节标题的位置
+    if (preg_match_all($pattern, $content, $matches, PREG_OFFSET_CAPTURE)) {
+        $titleCount = count($matches[0]);
+        
+        for ($i = 0; $i < $titleCount; $i++) {
+            // 获取当前章节标题
+            $titleLine = trim($matches[0][$i][0]);
+            // 去除标题开头的特殊符号
+            $cleanTitle = preg_replace('/^[#*·\-_=\s]+/', '', $titleLine);
+            // 去除标题结尾的冒号和特殊符号
+            $cleanTitle = preg_replace('/[#*·::\s]+$/', '', $cleanTitle);
+            $cleanTitle = trim($cleanTitle);
+            
+            // 获取当前标题的结束位置
+            $titleEndPos = $matches[0][$i][1] + strlen($matches[0][$i][0]);
+            
+            // 获取下一个章节标题的开始位置(如果存在)
+            $nextTitlePos = ($i < $titleCount - 1) ? $matches[0][$i + 1][1] : strlen($content);
+            
+            // 提取章节内容(从标题结束到下一个标题开始)
+            $chapterContent = substr($content, $titleEndPos, $nextTitlePos - $titleEndPos);
+            // 清理内容:去除前后空白和分隔线
+            $chapterContent = trim($chapterContent);
+            $chapterContent = preg_replace('/^[\-\s]+/u', '', $chapterContent);
+            $chapterContent = preg_replace('/[\-\s]+$/u', '', $chapterContent);
+            
+            if (!empty($cleanTitle) && !empty($chapterContent)) {
+                $chapters[] = [
+                    'title' => $cleanTitle,
+                    'content' => $chapterContent
+                ];
+            }
+        }
+    } else {
+        // 如果没有匹配到章节,返回整个内容
+        $chapters[] = [
+            'title' => '',
+            'content' => $content
+        ];
+    }
+    
+    return $chapters;
+}
+
 
 /**
  * 记录日志到数据库

+ 26 - 16
app/Services/DeepSeek/DeepSeekService.php

@@ -4133,7 +4133,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         ];
 
         if ($table_data['content']) {
-            $chapters = $this->splitContent($table_data['content']);
+            $chapters = splitContent($table_data['content']);
             $chapter_count = count($chapters);
             if ($chapter_count > 0) {
                 $table_data['start_episode_sequence'] = 1;
@@ -4928,7 +4928,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             } 
 
             if (isset($table_data['content']) && $table_data['content']) {
-                $chapters = $this->splitContent($table_data['content']);
+                $chapters = splitContent($table_data['content']);
                 $chapter_count = count($chapters);
                 if ($chapter_count > 0) {
                     $table_data['start_episode_sequence'] = 1;
@@ -5502,7 +5502,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             $full_content = $uploaded_content;
         }
         // 根据章节内容拆分章节
-        $chapters = $this->splitContent($full_content);
+        $chapters = splitContent($full_content);
         $chapter_content = isset($chapters[($episode_number-1)]['content']) ? $chapters[($episode_number-1)]['content'] : '';
         if (!$chapter_content) $chapter_content = $full_content;    // 如果无法拆分章节则直接用原文
         $messages = [];
@@ -6597,7 +6597,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         ];
 
         if ($table_data['content']) {
-            $chapters = $this->splitContent($table_data['content']);
+            $chapters = splitContent($table_data['content']);
             $chapter_count = count($chapters);
             if ($chapter_count > 0) {
                 $table_data['start_episode_sequence'] = 1;
@@ -7566,7 +7566,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             } 
 
             if (isset($table_data['content']) && $table_data['content']) {
-                $chapters = $this->splitContent($table_data['content']);
+                $chapters = splitContent($table_data['content']);
                 $chapter_count = count($chapters);
                 if ($chapter_count > 0) {
                     $table_data['start_episode_sequence'] = 1;
@@ -8375,7 +8375,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
             $full_content = $uploaded_content;
         }
         // 根据章节内容拆分章节
-        $chapters = $this->splitContent($full_content);
+        $chapters = splitContent($full_content);
         $chapter_content = isset($chapters[($episode_number-1)]['content']) ? $chapters[($episode_number-1)]['content'] : '';
         if (!$chapter_content) $chapter_content = $full_content;    // 如果无法拆分章节则直接用原文
         $messages = [];
@@ -8988,13 +8988,14 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         // 确定起始集数
         $startEpisodeNumber = $currentMaxEpisode + 1;
         
-        // 如果用户指定了起始集数(通过episode_number参数)
-        if (isset($data['episode_number'])) {
-            $userStartEpisode = (int)getProp($data, 'episode_number');
-            if ($userStartEpisode > $currentMaxEpisode) {
-                $startEpisodeNumber = $userStartEpisode;
-            }
-        }
+        // 不支持指定起始集数(必须按现有集数循序渐进)
+        // // 如果用户指定了起始集数(通过episode_number参数)
+        // if (isset($data['episode_number'])) {
+        //     $userStartEpisode = (int)getProp($data, 'episode_number');
+        //     if ($userStartEpisode > $currentMaxEpisode) {
+        //         $startEpisodeNumber = $userStartEpisode;
+        //     }
+        // }
         
         // 计算结束集数
         $endEpisodeNumber = $startEpisodeNumber + $generate_episode_number - 1;
@@ -11729,7 +11730,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         $chapters = [];
         
         // 匹配章节标题格式:
-        // 1. 标题独占一行
+        // 1. 标题可能独占一行,也可能在正文末尾或中间
         // 2. 格式支持:
         //    - **第一集**
         //    - 第一集:
@@ -11740,9 +11741,18 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
         // 4. 支持章节关键字:章、节、集、幕、场、回、话
         // 5. "第"字与数字、数字与章节关键字之间可能有空格
         // 6. 前后可能有#、*、·等修饰符号,后面可能有冒号、空格、标题文字等
+        
+        // 先预处理:将标题前后添加换行符,确保标题能被正确识别和拆分
+        // 匹配模式:可能有前缀符号 + "第" + 空格(可选) + 数字 + 空格(可选) + 章节关键字 + 可能的标题内容
+        $pattern = '/([#*·\-_=\s]*)第\s*([一二两三四五六七八九十百千万0-9]+)\s*([章节集幕场回话])([^第\n]*?)(?=第\s*[一二两三四五六七八九十百千万0-9]+\s*[章节集幕场回话]|$)/u';
+        
+        // 先在每个标题前插入换行符(如果前面不是换行的话)
+        $content = preg_replace('/([^\n])([#*·\-_=\s]*)第\s*([一二两三四五六七八九十百千万0-9]+)\s*([章节集幕场回话])/u', "$1\n\n$2第$3$4", $content);
+        
+        // 现在用修改后的模式匹配(标题应该在行首或接近行首)
         $pattern = '/^[#*·\s\-_=]*第\s*([一二两三四五六七八九十百千万0-9]+)\s*([章节集幕场回话]).*$/mu';
         
-        // 先用正则找出所有章节标题的位置
+        // 用正则找出所有章节标题的位置
         if (preg_match_all($pattern, $content, $matches, PREG_OFFSET_CAPTURE)) {
             $titleCount = count($matches[0]);
             
@@ -11751,7 +11761,7 @@ Q版卡通风格,头大身小,造型圆润可爱,线条简单,色彩明
                 $titleLine = trim($matches[0][$i][0]);
                 // 去除标题开头的特殊符号
                 $cleanTitle = preg_replace('/^[#*·\-_=\s]+/', '', $titleLine);
-                // 去除标题结尾的冒号
+                // 去除标题结尾的冒号和特殊符号
                 $cleanTitle = preg_replace('/[#*·::\s]+$/', '', $cleanTitle);
                 $cleanTitle = trim($cleanTitle);