作者 zhl

Merge remote-tracking branch 'origin/master' into zhl

... ... @@ -139,9 +139,9 @@ class DomainInfo extends Command
$serverIpModel = new ServersIp();
$domainCreateTaskModel = new DomainCreateTask();
$end_day = date('Y-m-d H:i:s', time() + 3 * 24 * 3600);//3天后到期
$list = $domainModel->where('status', '=', 1)->where('type', '!=', 2)->where('certificate_end_time', '<', $end_day)->get()->toArray();
$list = $domainModel->where('status', '=', 1)->where('type', '=', 1)->where('certificate_end_time', '<', $end_day)->get()->toArray();
foreach ($list as $v) {
$project_info = $projectModel->read(['id' => $v['project_id'], 'type' => ['!=', Project::TYPE_CLOSE]], ['serve_id']);
$project_info = $projectModel->read(['id' => $v['project_id'], 'type' => ['!=', Project::TYPE_CLOSE]], ['serve_id', 'project_type']);
if (!$project_info) {
continue;
}
... ... @@ -161,14 +161,20 @@ class DomainInfo extends Command
continue;
}
if ($project_info['project_type'] == Project::PROJECT_TYPE_SEO) {
$type = DomainCreateTask::TYPE_BLOG;
} else {
$type = DomainCreateTask::TYPE_MAIN;
}
//创建更新站点证书任务
$task_info = $domainCreateTaskModel->read(['type' => DomainCreateTask::TYPE_MAIN, 'domain_id' => $v['id'], 'status' => ['<', DomainCreateTask::STATUS_SUC]]);
$task_info = $domainCreateTaskModel->read(['type' => $type, 'domain_id' => $v['id'], 'status' => ['<', DomainCreateTask::STATUS_SUC]]);
if (!$task_info) {
$domainCreateTaskModel->add([
'server_id' => $servers_ip_info['servers_id'],
'project_id' => $v['project_id'],
'domain_id' => $v['id'],
'type' => DomainCreateTask::TYPE_MAIN
'type' => $type
]);
}
}
... ... @@ -186,7 +192,7 @@ class DomainInfo extends Command
$serverIpModel = new ServersIp();
$domainCreateTaskModel = new DomainCreateTask();
$end_day = date('Y-m-d H:i:s', time() + 3 * 24 * 3600);//3天后到期
$list = $domainModel->where('status', '=', 1)->where('amp_status', 1)->where('amp_type', '!=', 2)->where('amp_certificate_end_time', '<', $end_day)->get()->toArray();
$list = $domainModel->where('status', '=', 1)->where('amp_status', 1)->where('amp_type', '=', 1)->where('amp_certificate_end_time', '<', $end_day)->get()->toArray();
foreach ($list as $v) {
$domain_array = parse_url($v['domain']);
$host = $domain_array['host'] ?? $domain_array['path'];
... ... @@ -243,7 +249,7 @@ class DomainInfo extends Command
$serverIpModel = new ServersIp();
$domainCreateTaskModel = new DomainCreateTask();
$end_day = date('Y-m-d H:i:s', time() + 3 * 24 * 3600);//3天后到期
$list = $customModel->where('status', 1)->where('is_create', 1)->where('type', '!=', 2)->where('certificate_end_time', '<', $end_day)->get()->toArray();
$list = $customModel->where('status', 1)->where('is_create', 1)->where('type', '=', 1)->where('certificate_end_time', '<', $end_day)->get()->toArray();
foreach ($list as $v) {
$project_info = $projectModel->read(['id' => $v['project_id'], 'type' => ['!=', Project::TYPE_CLOSE]], ['serve_id']);
if (!$project_info) {
... ...
... ... @@ -67,7 +67,30 @@ class UpdateRoute extends Command
*/
public function handle()
{
return $this->settingSeo();
return $this->getNullRoute();
}
/**
* @remark :查询 路由为空的关键词项目id
* @name :getNullRoute
* @author :lyh
* @method :post
* @time :2025/4/21 11:52
*/
public function getNullRoute(){
$projectModel = new Project();
$lists = $projectModel->list(['delete_status' => 0,'extend_type'=>0,'type'=>['in',[1,2,3,4]]], 'id', ['id']);
foreach ($lists as $val) {
echo date('Y-m-d H:i:s') . '开始--项目的id:'. $val['id'] . PHP_EOL;
ProjectServer::useProject($val['id']);
$keywordModel = new Keyword();
$info = $keywordModel->read(['route'=>'']);
if($info !== false){
echo '存在路由为空--项目id:'.$val['id'].PHP_EOL;
}
DB::disconnect('custom_mysql');
}
return true;
}
public function keyword_actions(){
... ...
... ... @@ -68,6 +68,7 @@ class RecommendedSuppliers extends Command
if(!empty($title)){
$this->savePurchaser($v['project_id'],$title);
}else{
$this->deployBuildModel->edit(['is_supplier'=>0],['project_id'=>$v['project_id']]);
echo '关键词已取完'.PHP_EOL;
}
DB::disconnect('custom_mysql');
... ... @@ -152,7 +153,7 @@ class RecommendedSuppliers extends Command
];
ksort($data);
$token = 'company_list+'.date('Y-m-d').'+'.http_build_query($data);
// echo date('Y-m-d H:i:s') . '加密token:'.md5($token) . PHP_EOL;
$keyword = rtrim($keyword, "\r");
$param = [
'prod_desc'=>$keyword,
'token'=>md5($token),
... ... @@ -161,19 +162,18 @@ class RecommendedSuppliers extends Command
$res = http_post($url,json_encode($param));
echo '请求返回状态'. ($res['code']?? '').PHP_EOL;
// echo date('Y-m-d H:i:s') . json_encode($res) . PHP_EOL;
if(!empty($res) && isset($res['code']) && $res['code'] == 200 && !empty($res['data'])){
//保存多条数据
$saveData = [
'project_id'=>$project_id,
'keyword'=>$keyword,
'data'=>json_encode($res['data'])
];
$purchaserModel = new Purchaser();
$purchaserModel->add($saveData);
//保存多条数据
$saveData = [
'project_id'=>$project_id,
'keyword'=>$keyword,
'data'=>json_encode($res['data'] ?? '')
];
$purchaserModel = new Purchaser();
$purchaserModel->add($saveData);
if(isset($res['code']) && $res['code'] == 200 && !empty($res['data'])){
$this->savePurchaserInfo($project_id,$keyword,$res['data']);
}else{
$title = $this->getKeywords($project_id);
$this->savePurchaser($project_id,$title);
echo '未正常返回数据,跳过项目'.PHP_EOL;
}
return true;
}
... ... @@ -188,11 +188,11 @@ class RecommendedSuppliers extends Command
public function getKeywords($project_id){
$keywordModel = new Keyword();
$keyword_array = $this->getPurchaserList($project_id);
$info = $keywordModel->read(['title'=>['not in',$keyword_array]],'title');
if($info === false){
$title = $keywordModel->whereNotIn('title', $keyword_array)->inRandomOrder()->limit(1)->value('title');
if(empty($title)){
return '';
}
return $info['title'] ?? '';
return $title;
}
/**
... ... @@ -205,6 +205,9 @@ class RecommendedSuppliers extends Command
public function savePurchaserInfo($project_id,$keyword,$data){
$purchaserInfoModel = new PurchaserInfo();
foreach ($data as $k =>$v){
if(empty($v['buyer_id'])){
continue;
}
$v['project_id'] = $project_id;
$v['keyword'] = $keyword;
$v['email'] = json_encode($v['email']??[],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
... ...
... ... @@ -5,11 +5,13 @@ namespace App\Console\Commands\Tdk;
use App\Helper\Arr;
use App\Models\Product\Keyword;
use App\Models\Project\KeywordPrefix;
use App\Models\Project\Project;
use App\Models\Project\ProjectUpdateTdk;
use App\Services\ProjectServer;
use App\Utils\LogUtils;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
... ... @@ -64,24 +66,36 @@ class RerunSeoTdk extends Command
}
/**
* 判断seo_title 前缀有wholesale或cheap的词,后缀也有 manufacturer,factory,exporter,company
* 判断seo_title 前缀有wholesale或cheap或buy的词,后缀也有 manufacturer,factory,exporter,company
* 判断关键词最后一个词是前缀的词,前后缀都不拼
* @author zbj
* @date 2025/4/12
*/
public function judgeAnomalies($project_id){
dump($project_id);
$all_prefixes = $this->getAllPrefix(1, $project_id);
$all_prefixes = array_map('strtolower', $all_prefixes);
//获取当前项目的所有分类
$seo_titles = Keyword::pluck('seo_title', 'id')->toArray();
$list = Keyword::select('title', 'seo_title', 'id')->get()->toArray();
//新闻 seo_keyword 和 分类名一样的
$ids = [];
foreach ($seo_titles as $id=>$seo_title){
if(!Str::startsWith(strtolower($seo_title), ['wholesale', 'cheap'])){
foreach ($list as $k=>$item){
$seo_title = $item['seo_title'];
$id = $item['id'];
$title = $item['title'];
if(Str::startsWith(strtolower($seo_title), ['wholesale', 'cheap', 'buy']) && Str::contains(strtolower($seo_title), ['manufacturer', 'manufacturers', 'factory', 'factories', 'exporter', 'exporters', 'company', 'companies', 'supplier', 'suppliers'])){
$ids[] = $id;
dump($seo_title);
continue;
}
if(!Str::contains(strtolower($seo_title), ['manufacturer', 'manufacturers', 'factory', 'factories', 'exporter', 'exporters', 'company', 'companies', 'supplier', 'suppliers'])){
$topic_words = explode(' ', strtolower($title));
//关键词最后一个是前缀 且 有前后缀
if(in_array(Arr::last($topic_words), $all_prefixes) && $title != $seo_title){
$ids[] = $id;
dump($seo_title);
continue;
}
dump($seo_title);exit;
$ids[] = $id;
}
$count = count($ids);
... ... @@ -147,4 +161,14 @@ class RerunSeoTdk extends Command
// ProjectUpdateTdk::add_task($project_id);
// }
// }
public function getAllPrefix($type, int $project_id = 0){
$cache_key = 'AllPrefix_' . $type . '_' . $project_id;
$data = Cache::get($cache_key);
if(!$data){
$data = KeywordPrefix::whereIn('project_id', [0, $project_id])->where('type', $type)->pluck('keyword')->toArray();
Cache::put($cache_key, $data, 600);
}
return $data;
}
}
... ...
... ... @@ -372,10 +372,10 @@ class UpdateSeoTdk extends Command
} else if ($table == 'gl_product_keyword' && $field == 'seo_title') {
# TODO 聚合页seo title 特殊处理 前缀_1 . 关键词 . 后缀_2
$seo_title = $v[$this->topic_fields[$table]];;
//只有推广项目 且未标记特殊前后缀 才加 前后缀
if($project->type == Project::TYPE_TWO && !in_array(8, explode(',', $project->deploy_optimize->special))) {
//只有推广项目 才加 前后缀
if($project->type == Project::TYPE_TWO) {
$prefix = $this->getPrefixKeyword($project_id, 'prefix', 1, $seo_title);
$suffix = $this->getPrefixKeyword($project_id, 'suffix', 2, $prefix . ' ' . $seo_title);
$suffix = $this->getPrefixKeyword($project_id, 'suffix', 2, trim($prefix . ' ' . $seo_title));
if(Str::startsWith($suffix, ', ')){
$seo_title = $prefix . ' ' . $seo_title . $suffix;
}else{
... ... @@ -567,18 +567,31 @@ class UpdateSeoTdk extends Command
}
//前后缀(包括自定义前后缀)如果已经存在,就不在拼接当前类型 后缀只包含了一个,要再拼一个(需去重)
$all_prefixes = $this->getAllPrefix($type == 'prefix' ? 1 : 2, $project_id);
$all_prefixes = $this->getAllPrefix(1, $project_id);
$all_prefixes = array_map('strtolower', $all_prefixes);
$all_suffixes = $this->getAllPrefix(2, $project_id);
$all_suffixes = array_map('strtolower', $all_suffixes);
//in,for,with,to,near,from 这些介词 只拼前缀,不拼后缀
$preposition = ['in', 'for', 'with', 'to', 'near','from'];
//标题拆成词
$topic_words = explode(' ', strtolower($topic));
//关键词最后一个词是前缀的词,前后缀都不拼
if(in_array(Arr::last($topic_words), $all_prefixes)){
return $str;
}
$i= 0;
foreach ($topic_words as $topic_word){
//包含了前后缀
if(in_array($topic_word, $all_prefixes)){
//关键词本身包含了前缀就不拼前缀,只拼后缀
if(in_array($topic_word, $all_prefixes) && $type == 'prefix'){
return $str;
}
//关键词本身包含了后缀,可拼前缀,也可以再拼一个不重复的后缀,包含两个后缀就不拼后缀了
if(in_array($topic_word, $all_suffixes) && $type == 'suffix'){
//前缀包含一个就不拼了 后缀包含两个才不再拼
if($i == $num - 1){
return $str;
... ... @@ -591,7 +604,6 @@ class UpdateSeoTdk extends Command
if(in_array($topic_word, $preposition) && $type == 'suffix'){
return $str;
}
}
//services/service 结尾的词,后缀不拼manufacturer,factory
... ... @@ -603,13 +615,13 @@ class UpdateSeoTdk extends Command
$ban = array_merge($ban, ['services', 'service']);
}
//前缀有wholesale或cheap的词,后缀不拼 manufacturer,factory,exporter,company
if (Str::startsWith(strtolower($topic), ['wholesale', 'cheap']) && $type == 'suffix') {
//有wholesale或cheap的词,后缀不拼 manufacturer,factory,exporter,company
if (Str::contains(strtolower($topic), ['wholesale', 'cheap', 'buy']) && $type == 'suffix') {
$ban = array_merge($ban, ['manufacturer', 'manufacturers', 'factory', 'factories', 'exporter', 'exporters', 'company', 'companies', 'supplier', 'suppliers']);
}
//关键词以manufacturer,factory,exporter,company结尾, 前缀不拼wholesale或cheap的词
if (Str::endsWith(strtolower($topic), ['manufacturer', 'manufacturers', 'factory', 'factories', 'exporter', 'exporters', 'company', 'companies', 'supplier', 'suppliers']) && $type == 'prefix') {
$ban = array_merge($ban, ['wholesale', 'cheap']);
$ban = array_merge($ban, ['wholesale', 'cheap', 'buy']);
}
//关键词是否包含 品牌词
... ... @@ -660,7 +672,7 @@ class UpdateSeoTdk extends Command
$keywords[] = $v;
$num--;
}
if ($type == 'suffix' && count($keywords) == 1 && in_array(Arr::last($topic_words), $all_prefixes)) {
if ($type == 'suffix' && count($keywords) == 1 && in_array(Arr::last($topic_words), $all_suffixes)) {
return ', ' . $keywords[0];
}
return implode(', ', $keywords);
... ... @@ -774,9 +786,12 @@ class UpdateSeoTdk extends Command
Cache::forget($cache_key);
}
}
$a = $text;
$text = Common::deal_keywords($text);
$text = Common::deal_str($text);
if(!$text){
echo getmypid() . ' ' . 'AI生成结果['.$a.']被关键词过滤' . PHP_EOL;
}
//包含这写字 重新生成
if(Str::contains(Str::lower($text), ['[your brand]', '[brand name]'])){
... ...
... ... @@ -39,17 +39,64 @@ class Temp extends Command
*/
protected $description = '临时脚本(akun)';
public function handle()
public function handle(){
}
/**
* www.docareco.com批量设置301跳转
* @author Akun
* @date 2025/04/21 16:12
*/
public function setDomain301()
{
$domain_extend_config = DomainInfo::where('domain', 'www.docareco.com')->value('extend_config');
$domain_origin_list = $domain_extend_config ? array_column($domain_extend_config, 'origin') : [];
//读取csv文件
$file = 'C:\Users\Akun\Desktop\有排名网页-还未做301-4.21.csv';
$line_of_text = [];
try {
$file_handle = fopen($file, 'r');
while (!feof($file_handle)) {
$line_of_text[] = fgetcsv($file_handle, 0, ',');
}
fclose($file_handle);
} catch (\Exception $e) {
$this->output($e->getMessage());
}
if (count($line_of_text) > 1) {
foreach ($line_of_text as $k => $v) {
if ($k > 0 && $v) {
$origin = str_replace('https://www.docareco.com', '', $v[0]);
$target = str_replace('https://www.docareco.com', '', $v[1]);
if (!in_array($origin, $domain_origin_list)) {
$domain_extend_config[] = [
'origin' => $origin,
'target' => $target
];
}
}
}
}
DomainInfo::where('domain', 'www.docareco.com')->update(['extend_config' => Arr::a2s($domain_extend_config)]);
$this->output('success');
}
/**
* 未被标注 特殊前后缀 && 未达标项目 && 优化开始时间 > 2025-01-01 00:00:00 ,开启自动添加聚合页关键词的前后缀关键词配置
* @author Akun
* @date 2025/04/02 14:00
*/
public function changeIsAutoKeywords(){
public function changeIsAutoKeywords()
{
$project_list = DeployOptimize::where('special', 'not like', '%,8,%')->where('start_date', '>', '2025-01-01 00:00:00')->get();
foreach ($project_list as $project) {
... ...
... ... @@ -9,6 +9,7 @@ use App\Models\User\UserLogin as UserLoginModel;
use Illuminate\Encryption\Encrypter;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
/**
* @name:
... ... @@ -213,18 +214,23 @@ class Common
}
$keyword = str_replace($str,'',$keyword);
$keyword = trim($keyword,'.');
if( (strpos(strtolower($keyword),'hope') === false || strpos(strtolower($keyword),'hopein') !== false)
&& (strpos(strtolower($keyword),'remember') === false || strpos(strtolower($keyword),'rememberance') !== false)
&& strpos(strtolower($keyword),'help') === false
&& strpos(strtolower($keyword),'website') === false
&& strpos(strtolower($keyword),'search keywords') === false
&& strpos(strtolower($keyword),'here are 8') === false
&& strpos(strtolower($keyword),'search keywords') === false
&& strpos(strtolower($keyword),'thank you') === false
&& (strpos(strtolower($keyword),'thanks') === false || strpos(strtolower($keyword),'thanksgiving') !== false)
&& strpos(strtolower($keyword),'copywriter') === false ){
$ar_keywords[] = $keyword;
if(Str::contains($keyword, ['search keywords', 'here are 8', 'thank you'])){
continue;
}
$keyword_words = explode(' ', $keyword);
$is_contains = false;
foreach ($keyword_words as $word){
if(in_array($word, ['hope', 'remember', 'help', 'website', 'thanks', 'copywriter'])){
$is_contains = true;
break;
}
}
if($is_contains){
continue;
}
$ar_keywords[] = $keyword;
}
}
return implode(', ',$ar_keywords);
... ...
... ... @@ -37,12 +37,27 @@ class CheckListController extends BaseController
* @time :2025/4/17 9:31
*/
public function lists(){
$this->map['status'] = 1;
$field = ['id','status','sort','text','created_at'];
$data = $this->model->lists($this->map,$this->page,$this->row,'id',$field);
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :获取分页检查清单数据
* @name :lists
* @author :lyh
* @method :post
* @time :2025/4/17 9:31
*/
public function list(){
$this->map['status'] = 1;
$field = ['id','status','sort','text','created_at'];
$data = $this->model->list($this->map,'id',$field);
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :获取数据详情
* @name :info
* @author :lyh
... ... @@ -67,6 +82,7 @@ class CheckListController extends BaseController
* @time :2025/4/17 9:32
*/
public function save(){
$this->param['operator_id'] = $this->manage['id'];
if(isset($this->param['id']) && !empty($this->param['id'])){
$id = $this->param['id'];
$this->model->edit($this->param,['id'=>$this->param['id']]);
... ...
... ... @@ -195,17 +195,36 @@ class DomainInfoLogic extends BaseLogic
}
}
//如果要开通amp站点,判断m域名是否已经解析
$domain_array = parse_url($info['domain']);
$host = $domain_array['host'] ?? $domain_array['path'];
$host_array = explode('.',$host);
if($this->param['type'] == 3){
//需要申请通配符证书,判断_acme-challenge是否已经解析
$host_array_ssl = $host_array;
if (count($host_array_ssl) <= 2) {
array_unshift($host_array_ssl, '_acme-challenge');
} else {
$host_array_ssl[0] = '_acme-challenge';
}
$ssl_domain = implode('.',$host_array_ssl);
$ssl_records = dns_get_record($ssl_domain,DNS_CNAME);
$ssl_target = $ssl_records[0]['target']??'';
if($ssl_target != '_acme-challenge.globalsosslcheck.com'){
$this->fail('缺少通配符证书必要的解析记录:'.$ssl_domain);
}
}
if(isset($this->param['amp_status']) && $this->param['amp_status'] == 1){
$domain_array = parse_url($info['domain']);
$host = $domain_array['host'] ?? $domain_array['path'];
$host_array = explode('.',$host);
if (count($host_array) <= 2) {
array_unshift($host_array, 'm');
//需要开通amp站点,判断m域名是否已经解析
$host_array_amp = $host_array;
if (count($host_array_amp) <= 2) {
array_unshift($host_array_amp, 'm');
} else {
$host_array[0] = 'm';
$host_array_amp[0] = 'm';
}
$amp_domain = implode('.',$host_array);
$amp_domain = implode('.',$host_array_amp);
if(!check_domain_record($amp_domain, $serversIpInfo)){
$this->fail('AMP站点域名' . $amp_domain . '未解析至目标服务器');
}
... ...
... ... @@ -496,7 +496,7 @@ class RankDataLogic extends BaseLogic
$without_project_ids = []; //不用处理排名的项目
$without_extension_project_ids = [658]; //是否达标只统计主词的
$extension_project_ids = [354]; //扩展词也到达标的
$compliance_project_ids = [2163,257,823]; //直接达标处理的
$compliance_project_ids = [2163,257,823,1750]; //直接达标处理的
$ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250];//暂停的项目
$uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
//一个项目多个api_no
... ...
... ... @@ -45,8 +45,8 @@ class OptimizeCheckLog extends Base
if(isset($param['images'])){
$param['images'] = Arr::a2s($param['images'] ?? []);
}
$this->param['operator_id'] = $manage_id;
$this->param['date'] = date('Y-m-d hH:i:s');
$param['operator_id'] = $manage_id;
$param['date'] = $param['date'] ?? date('Y-m-d H:i:s');
return $param;
}
}
... ...
... ... @@ -309,7 +309,8 @@ Route::middleware(['aloginauth'])->group(function () {
//检查列表
Route::prefix('check_list')->group(function () {
Route::any('/', [Aside\Optimize\CheckListController::class, 'lists'])->name('admin.check_list');
Route::any('/', [Aside\Optimize\CheckListController::class, 'lists'])->name('admin.check_lists');
Route::any('/list', [Aside\Optimize\CheckListController::class, 'list'])->name('admin.check_list');
Route::any('/info', [Aside\Optimize\CheckListController::class, 'info'])->name('admin.check_list_info');
Route::any('/save', [Aside\Optimize\CheckListController::class, 'save'])->name('admin.check_list_save');
Route::any('/del', [Aside\Optimize\CheckListController::class, 'del'])->name('admin.check_list_del');
... ...