Browse Source
feat(queue): 新增爆文复刻队列处理功能
feat(queue): 新增爆文复刻队列处理功能
- 创建 ExpiosiveReplica 队列消费者类,实现文章内容抓取与AI复刻逻辑 - 实现从URL抓取HTML并提取标题和内容的功能 - 添加配图获取及AI指令整合逻辑 - 更新 CreationTask 队列中配图分类查询方式,直接使用任务中的分类ID - 修改 ExpiosiveReplica 模型,增加 ai_time 字段的格式化方法 - 在 ExpiosiveReplicaService 中投递队列消息,并优化列表查询字段master
4 changed files with 232 additions and 5 deletions
-
4app/model/ExpiosiveReplica.php
-
7app/queue/redis/CreationTask.php
-
222app/queue/redis/ExpiosiveReplica.php
-
4app/service/ExpiosiveReplicaService.php
@ -0,0 +1,222 @@ |
|||
<?php |
|||
namespace app\queue\redis; |
|||
|
|||
use app\dao\AiCommandDao; |
|||
use app\dao\EnterprisePortraitLibraryDao; |
|||
use app\dao\ExpiosiveReplicaDao; |
|||
use plugin\piadmin\app\utils\openai\OpenAiClient; |
|||
use Webman\RedisQueue\Consumer; |
|||
|
|||
class ExpiosiveReplica implements Consumer |
|||
{ |
|||
// 要消费的队列名
|
|||
public $queue = 'expiosive_replica'; |
|||
|
|||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
|||
public $connection = 'default'; |
|||
|
|||
//抓取文章提示词
|
|||
private $fetchWebPrompt = '- Role: HTML内容解析专家和信息提取工程师 |
|||
- Background: 用户需要从提供的HTML代码中精确提取文章标题和内容。这表明用户已经获取了网页的HTML源代码,需要从中提取特定的信息,以便进行进一步的处理或分析。 |
|||
- Profile: 你是一位在HTML内容解析和信息提取领域有着丰富经验的专家,能够精准地从HTML代码中提取所需的信息。你熟悉HTML结构和数据提取技术,能够高效地完成任务。 |
|||
- Skills: 你具备HTML解析能力、数据提取技术、信息筛选技巧以及对网页结构的深刻理解。能够根据用户提供的HTML代码,准确提取文章标题和内容。 |
|||
- Goals: 根据用户提供的HTML代码,精确提取文章标题和内容,确保提取的信息准确无误。 |
|||
- Constrains: 提取的内容必须严格来自用户提供的HTML代码,确保信息的真实性和完整性。避免提取无关内容,确保提取的文章标题和内容清晰可读。 |
|||
- OutputFormat: 输出格式为JSON格式,将提取的文章标题放在`title`字段中,内容放在`content`字段中。 |
|||
- Workflow: |
|||
1. 接收用户提供的HTML代码。 |
|||
2. 解析HTML代码,定位文章标题和内容的HTML元素。 |
|||
3. 提取文章标题和内容,并进行格式化处理,确保信息清晰可读。 |
|||
4. 将提取的信息整合到JSON格式中,包括`title`和`content`字段。 |
|||
- Examples: |
|||
- 假设用户提供的HTML代码如下: |
|||
```html |
|||
<html> |
|||
<head> |
|||
<title>2025年科技行业发展趋势</title> |
|||
</head> |
|||
<body> |
|||
<h1>2025年科技行业发展趋势</h1> |
|||
<p>随着科技的飞速发展,2025年科技行业呈现出许多新的趋势。</p> |
|||
<p>人工智能在医疗、教育和交通等领域的应用越来越广泛。</p> |
|||
<p>5G技术的普及也推动了物联网的发展。</p> |
|||
<p>此外,量子计算和区块链技术也在逐步走向商业化应用。</p> |
|||
</body> |
|||
</html> |
|||
``` |
|||
提取结果如下: |
|||
```json |
|||
{ |
|||
"title": "2025年科技行业发展趋势", |
|||
"content": "随着科技的飞速发展,2025年科技行业呈现出许多新的趋势。人工智能在医疗、教育和交通等领域的应用越来越广泛。5G技术的普及也推动了物联网的发展。此外,量子计算和区块链技术也在逐步走向商业化应用。" |
|||
}'; |
|||
|
|||
//爆文复刻用提示词
|
|||
private $defaultPrompt = '- Role: 爆文复刻专家、内容优化顾问及视觉内容整合师 |
|||
- Background: 用户需要对提供的标题和文章进行复刻,以满足特定的要求。用户会提供一些配图,并指定在文章合适的位置插入这些图片。这意味着用户希望在保留原文核心内容和风格的基础上,对文章进行优化和调整,使其更接近“爆文”的标准,同时通过视觉元素增强文章的吸引力和可读性。 |
|||
- Profile: 你是一位在爆文创作、内容优化和视觉内容整合领域有着丰富经验的专家,能够精准地把握爆文的特点和用户的需求,对文章进行高质量的复刻。你熟悉各种写作风格和内容结构,能够根据用户的要求,对文章进行有效的调整和优化,同时保留原文的核心价值和风格。 |
|||
- Skills: 你具备爆文创作能力、内容优化技巧、语言表达能力、视觉内容整合能力以及对用户需求的敏锐洞察力。能够根据用户提供的标题、文章和配图,结合复刻要求,对文章进行精准的调整和优化,并合理插入配图。 |
|||
- Goals: 根据用户提供的标题、文章和配图,按照用户的要求进行复刻,确保复刻后的文章更接近“爆文”的标准,同时保留原文的核心内容和风格,并在合适的位置插入配图,增强文章的视觉效果和可读性。 |
|||
- Constrains: 复刻后的文章必须严格遵循用户的要求,包括内容调整、风格优化、语言润色等。确保复刻后的文章在满足要求的同时,保持原有的核心信息和风格特点。配图插入位置应合理,与文章内容紧密相关,增强文章的可读性和视觉效果。 |
|||
- OutputFormat: 输出格式为完整的文章正文,包括复刻后的标题和内容。如果用户有特定的格式要求,应严格按照要求输出。配图应插入到文章的合适位置,图片数量符合用户指定的要求。 |
|||
- Workflow: |
|||
1. 接收用户提供的标题、文章和配图。 |
|||
2. 仔细分析用户提出的复刻要求,明确复刻的方向和重点。 |
|||
3. 根据复刻要求,对文章的标题和内容进行优化和调整,提升文章的吸引力和可读性。 |
|||
4. 确定配图的插入位置,确保图片与文章内容紧密相关,增强视觉效果。 |
|||
5. 将配图合理插入到文章的合适位置,完成复刻。 |
|||
6. 审核复刻后的文章,确保内容符合用户的要求,语言流畅且逻辑清晰,用户提出的要求仅针对提供的标题和内容,不针对复刻后的标题和内容。 |
|||
- Examples: |
|||
- 假设用户提供的标题是“如何提高工作效率”,文章内容如下: |
|||
``` |
|||
在当今快节奏的工作环境中,提高工作效率是每个职场人士都关心的问题。以下是一些实用的建议: |
|||
- 制定清晰的工作计划。 |
|||
- 优先处理重要任务。 |
|||
- 避免不必要的干扰。 |
|||
- 定期休息,保持精力充沛。 |
|||
``` |
|||
用户提供了两张配图,并要求在合适的位置插入: |
|||
```json |
|||
{ |
|||
"title": "工作效率翻倍的秘密:职场高手的4个绝招", |
|||
"content": "在快节奏的职场竞争中,工作效率就是生命线!今天,就来揭秘那些职场高手如何轻松搞定工作,效率翻倍的秘密。\n\n首先,高手们都会制定一份超清晰的工作计划,每一步都精准无误。其次,他们总是优先搞定那些最重要的任务,绝不拖泥带水。\n\n再来,他们懂得如何屏蔽那些无意义的干扰,专注就是他们的超能力。最后,别小看定期休息,这可是保持精力充沛的不二法门。赶紧试试这些绝招,让你的工作效率瞬间提升!" |
|||
}。 |
|||
我提供的JSON数据:配图(images)。创作要求(prompt),仅针对提供的内容(content),不针对创作的文章,尤其是不影响配图的插入。标题(title),内容(contnet)。数据:'; |
|||
|
|||
// 消费
|
|||
public function consume($data) |
|||
{ |
|||
echo "开始消费爆发复刻,数据ID为:" . $data['replica_id'] . "\n"; |
|||
//获取复刻任务
|
|||
$replicaDao = app()->make(ExpiosiveReplicaDao::class); |
|||
//状态改为复刻
|
|||
$replicaDao->update($data['replica_id'], ['status' => 2]); |
|||
//获取复刻任务明细
|
|||
$replicaTask = $replicaDao->get($data['replica_id']); |
|||
//解析url获取文章内容
|
|||
$html = $this->fetchArticleContent($replicaTask['url']); |
|||
$fetch_prompt = $this->fetchWebPrompt . ',需要提取的html为:' . $html; |
|||
$result = OpenAiClient::chat($fetch_prompt); |
|||
$title = $result['content']['title']; |
|||
$content = $result['content']['content']; |
|||
//拼接提示词
|
|||
$prompts = array_merge($this->getPortraitLibrary($replicaTask),$this->getAiCommand($replicaTask)); |
|||
$prompts['title'] = $title; |
|||
$prompts['content'] = $content; |
|||
$finalPrompt = $this->defaultPrompt . '\n' . json_encode($prompts, JSON_UNESCAPED_UNICODE); |
|||
// echo "最终提示词:\n";
|
|||
// var_export($finalPrompt);
|
|||
$airesult = OpenAiClient::chat($finalPrompt); |
|||
$updata = [ |
|||
'url_web' => $html, |
|||
'title' => $result['content']['title'], |
|||
'content' => $result['content']['content'], |
|||
'ai_title' => $airesult['content']['title'], |
|||
'ai_content' => $airesult['content']['content'], |
|||
'status' => 3, |
|||
'ai_time' => time() |
|||
]; |
|||
var_export($updata); |
|||
//更改任务状态为完成
|
|||
$replicaDao->update($data['replica_id'], $updata); |
|||
var_export('任务完成'); |
|||
} |
|||
|
|||
public function onConsumeFailure(\Throwable $e, $package) |
|||
{ |
|||
echo "执行失败\n"; |
|||
echo $e->getMessage() . "\n"; |
|||
echo $e->getFile() . "\n"; |
|||
echo $e->getLine() . "\n"; |
|||
// 无需反序列化
|
|||
var_export($package); |
|||
//记录失败
|
|||
$replicaDao = app()->make(ExpiosiveReplicaDao::class); |
|||
$replicaDao->update($package['data']['replica_id'], [ |
|||
'status' => 4, |
|||
'try_count' => $package['attempts'], |
|||
'status_msg' => $package['error'] |
|||
]); |
|||
} |
|||
|
|||
/** |
|||
* 获取配图及使用数量 |
|||
*/ |
|||
private function getPortraitLibrary($replicaTask) |
|||
{ |
|||
echo "开始获取配图\n"; |
|||
$libraryDao = app()->make(EnterprisePortraitLibraryDao::class); |
|||
$library = $libraryDao->getColumn(['category_id' => $replicaTask['portrait_category_id']], 'url'); |
|||
echo "获取到配图:" . count($library) . "\n"; |
|||
var_export($library); |
|||
if (!$library) { |
|||
return [ |
|||
'images' => [], |
|||
]; |
|||
} |
|||
return [ |
|||
'images' => $library, |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* 获取创作指令 |
|||
* type = 3 流量复刻 |
|||
*/ |
|||
private function getAiCommand($replicaTask) |
|||
{ |
|||
echo "开始获取指令:" . 3 . "\n"; |
|||
$aiCommandDao = app()->make(AiCommandDao::class); |
|||
$ai_command_id = $replicaTask['ai_command_id']; |
|||
$command = $aiCommandDao->getOne([ |
|||
'type' => 3, |
|||
'id' => $ai_command_id |
|||
]); |
|||
echo "获取到指令:" . $command['content'] . "\n"; |
|||
if (!$command) { |
|||
return [ |
|||
'prompt' => '' |
|||
]; |
|||
} |
|||
return [ |
|||
'prompt' => $command['content'] |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* 从URL抓取文章内容 |
|||
* @param string $url |
|||
* @return string |
|||
*/ |
|||
public function fetchArticleContent(string $url): string |
|||
{ |
|||
// 使用 cURL 获取网页内容
|
|||
$ch = curl_init(); |
|||
curl_setopt($ch, CURLOPT_URL, $url); |
|||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
|||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); |
|||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'); |
|||
curl_setopt($ch, CURLOPT_TIMEOUT, 30); |
|||
$html = curl_exec($ch); |
|||
curl_close($ch); |
|||
// 移除script标签及其内容
|
|||
$html = preg_replace('/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/mi', '', $html); |
|||
// 移除style标签及其内容
|
|||
$html = preg_replace('/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/mi', '', $html); |
|||
// 移除link标签(通常用于引入CSS)
|
|||
$html = preg_replace('/<link\b[^>]*>/mi', '', $html); |
|||
// 移除meta标签
|
|||
$html = preg_replace('/<meta\b[^>]*>/mi', '', $html); |
|||
// 移除所有标签的style属性(行内样式)
|
|||
$html = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $html); |
|||
// 移除所有标签的class属性
|
|||
$html = preg_replace('/(<[^>]+) class=".*?"/i', '$1', $html); |
|||
// 移除所有标签的id属性
|
|||
$html = preg_replace('/(<[^>]+) id=".*?"/i', '$1', $html); |
|||
// 移除多余的空白行
|
|||
$html = preg_replace('/^\s*[\r\n]/m', '', $html); |
|||
$html = str_replace(' ', '', $html); |
|||
return $html; |
|||
|
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue