作者 赵彬吉
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GoogleSearchKeyword.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/3/31 11:29
  8 + */
  9 +
  10 +namespace App\Console\Commands\GoogleSearch;
  11 +
  12 +use App\Models\Com\NoticeLog;
  13 +use App\Models\Domain\DomainInfo;
  14 +use App\Models\GoogleSearch\GoogleSearch;
  15 +use App\Models\GoogleSearch\GoogleSearchDetail;
  16 +use App\Models\Project\Project;
  17 +use App\Services\GoogleSearchService;
  18 +use App\Services\ProjectServer;
  19 +use Illuminate\Console\Command;
  20 +use Illuminate\Support\Facades\DB;
  21 +
  22 +/**
  23 + * @remark :客户搜索词
  24 + * @name :GoogleSearchKeyword
  25 + * @author :lyh
  26 + * @method :post
  27 + * @time :2025/3/31 11:29
  28 + */
  29 +class GoogleSearchKeyword extends Command
  30 +{
  31 + /**
  32 + * The name and signature of the console command.
  33 + *
  34 + * @var string
  35 + */
  36 + protected $signature = 'search_keyword';
  37 +
  38 + /**
  39 + * The console command description.
  40 + *
  41 + * @var string
  42 + */
  43 + protected $description = 'google搜索词';
  44 +
  45 + public $googleService;
  46 + public $searchModel;
  47 + public $detailModel;
  48 +
  49 + public function __construct()
  50 + {
  51 + $this->googleService = new GoogleSearchService();
  52 + $this->searchModel = new GoogleSearch();
  53 + $this->detailModel = new GoogleSearchDetail();
  54 + parent::__construct();
  55 + }
  56 +
  57 + /**
  58 + * @remark :拉取google搜索数据
  59 + * @name :handle
  60 + * @author :lyh
  61 + * @method :post
  62 + * @time :2025/3/31 11:37
  63 + */
  64 + public function handle(){
  65 + $projectModel = new Project();
  66 + $lists = $projectModel->list(['delete_status' => 0,'type'=>['!=',$projectModel::TYPE_ONE]], 'id', ['id']);
  67 + $domainModel = new DomainInfo();
  68 + foreach ($lists as $val) {
  69 + echo date('Y-m-d H:i:s') . '开始--项目的id:'. $val['id'] . PHP_EOL;
  70 + $domainInfo = $domainModel->read(['project_id'=>$val['id']]);
  71 + if($domainInfo === false){
  72 + echo '域名不存在。'.PHP_EOL;
  73 + continue;
  74 + }
  75 + $typeData = [1=>'date', 2=>'query', 3=>'page', 4=>'device', 5=>'country'];
  76 + foreach ($typeData as $keyT => $valT){
  77 + $this->_action($domainInfo['domain'],$valT,$val['id']);
  78 + }
  79 + }
  80 + return true;
  81 + }
  82 +
  83 + /**
  84 + * @remark :执行的方法
  85 + * @name :_action
  86 + * @author :lyh
  87 + * @method :post
  88 + * @time :2025/3/31 11:30
  89 + */
  90 + public function _action($domain,$type,$project_id){
  91 + $data = $this->googleService->googleSearch($domain,$type);
  92 + if(empty($data)){
  93 + echo '域名:'.$domain.'拉取数据为空.'.PHP_EOL;
  94 + return false;
  95 + }
  96 + //保存一条主记录诗句
  97 + $this->searchModel->addReturnId(['date'=>date('Y-m-d'),'project_id'=>$project_id,'type'=>$type]);
  98 + $saveData = [];
  99 + $clicksNum = array_sum(array_column($data, 'clicks'));
  100 + $impressionsNum = array_sum(array_column($data, 'impressions'));
  101 + echo 'clicksNum:'.$clicksNum.PHP_EOL;
  102 + echo 'impressionsNum:'.$impressionsNum.PHP_EOL;
  103 + foreach ($data as $val){
  104 + $saveData[] = [
  105 + 'date'=>date('Y-m-d'),
  106 + 'project_id'=>$project_id,
  107 + 'type'=>$type,
  108 + 'keys'=>$val['keys'][0],
  109 + 'clicks'=>$val['clicks'],
  110 + 'click_rate'=>number_format($val['clicks'] / (($clicksNum == 0) ? 1 : $clicksNum), 2),
  111 + 'impressions'=>$val['impressions'],
  112 + 'impressions_rate'=>number_format($val['impressions'] / (($impressionsNum == 0) ? 1 : $impressionsNum), 2),
  113 + 'ctr'=>$val['ctr'],
  114 + 'position'=>$val['position'],
  115 + ];
  116 + }
  117 + if(!empty($saveData)){
  118 + DB::beginTransaction();
  119 + try {
  120 + //清空以前的数据
  121 + $this->detailModel->del(['project_id'=>$project_id,'type'=>$type]);
  122 + $this->detailModel->insertAll($saveData);
  123 + DB::commit();
  124 + }catch (\Exception $e){
  125 + DB::rollBack();
  126 + echo '重新添加数据失败:project_id'.$project_id.PHP_EOL;
  127 + }
  128 + }
  129 + return true;
  130 + }
  131 +}
@@ -39,7 +39,6 @@ class Kernel extends ConsoleKernel @@ -39,7 +39,6 @@ class Kernel extends ConsoleKernel
39 $schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1); 39 $schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1);
40 // 优化预设关键词 同步 20点会开始TDK生成 40 // 优化预设关键词 同步 20点会开始TDK生成
41 $schedule->command('optimize_set_keyword_sync')->dailyAt('20:00')->withoutOverlapping(1); 41 $schedule->command('optimize_set_keyword_sync')->dailyAt('20:00')->withoutOverlapping(1);
42 - $schedule->command('after_count')->dailyAt('01:00')->withoutOverlapping(1); //售后日统计 每天统计一次  
43 } 42 }
44 43
45 /** 44 /**
@@ -555,20 +555,23 @@ class OptimizeController extends BaseController @@ -555,20 +555,23 @@ class OptimizeController extends BaseController
555 ], [ 555 ], [
556 'project_id.required' => '项目id不能为空', 556 'project_id.required' => '项目id不能为空',
557 ]); 557 ]);
  558 + $domainModel = new DomainInfo();
  559 + $domainInfo = $domainModel->read(['project_id'=>$this->param['project_id']],['domain']);
  560 + if($domainInfo === false){
  561 + $this->response('success');
  562 + }
558 ProjectServer::useProject($this->param['project_id']); 563 ProjectServer::useProject($this->param['project_id']);
559 $aiBlogModel = new AiBlog(); 564 $aiBlogModel = new AiBlog();
560 - $list = $aiBlogModel->formatQuery(['route'=>['!=',null]])->pluck('route')->toArray(); 565 + $list = $aiBlogModel->list(['route'=>['!=',null]],'id',['route','new_title']);
  566 + $resultData = [];
561 if(!empty($list)){ 567 if(!empty($list)){
562 - $domainModel = new DomainInfo();  
563 - $DomainInfo = $domainModel->read(['project_id'=>$this->param['project_id']]);  
564 $DomainInfo['domain'] = $DomainInfo['domain'] ?? ''; 568 $DomainInfo['domain'] = $DomainInfo['domain'] ?? '';
565 - foreach ($list as $k => $v){  
566 - $v = ('https://'.$DomainInfo['domain'].'/') . 'blog/' . $v;  
567 - $list[$k] = $v; 569 + foreach ($list as $v){
  570 + $resultData[] = ('https://'.$DomainInfo['domain'].'/') . 'blog/' . $v['route'] . '/{' . $v['new_title'] . '}';
568 } 571 }
569 } 572 }
570 DB::disconnect('custom_mysql'); 573 DB::disconnect('custom_mysql');
571 - $this->response('success',Code::SUCCESS,$list); 574 + $this->response('success',Code::SUCCESS,$resultData);
572 } 575 }
573 576
574 /** 577 /**
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 * @time :2025/3/25 14:23 7 * @time :2025/3/25 14:23
8 */ 8 */
9 9
10 -namespace App\Http\Controllers\Bside\GoogleKeywordInsight; 10 +namespace App\Http\Controllers\Bside\GoogleKeyword;
11 11
12 use App\Enums\Common\Code; 12 use App\Enums\Common\Code;
13 use App\Http\Controllers\Bside\BaseController; 13 use App\Http\Controllers\Bside\BaseController;
@@ -7,10 +7,13 @@ @@ -7,10 +7,13 @@
7 * @time :2025/3/27 13:53 7 * @time :2025/3/27 13:53
8 */ 8 */
9 9
10 -namespace App\Http\Controllers\Bside\GoogleKeywordInsight; 10 +namespace App\Http\Controllers\Bside\GoogleKeyword;
11 11
12 use App\Enums\Common\Code; 12 use App\Enums\Common\Code;
13 use App\Http\Controllers\Bside\BaseController; 13 use App\Http\Controllers\Bside\BaseController;
  14 +use App\Models\Com\NoticeLog;
  15 +use App\Models\GoogleSearch\GoogleSearch;
  16 +use App\Models\GoogleSearch\GoogleSearchDetail;
14 use App\Services\GoogleSearchService; 17 use App\Services\GoogleSearchService;
15 18
16 class GoogleSearchController extends BaseController 19 class GoogleSearchController extends BaseController
@@ -24,14 +27,14 @@ class GoogleSearchController extends BaseController @@ -24,14 +27,14 @@ class GoogleSearchController extends BaseController
24 */ 27 */
25 public function getSearchList(){ 28 public function getSearchList(){
26 $this->request->validate([ 29 $this->request->validate([
27 - 'search' => 'required' 30 + 'type' => 'required'
28 ],[ 31 ],[
29 - 'search.required' => '搜索类型不能为空', 32 + 'type.required' => '搜索类型不能为空',
30 ]); 33 ]);
31 - //获取当前项目域名  
32 - $domain = parse_url($this->user['domain'], PHP_URL_HOST);  
33 - $googleService = new GoogleSearchService();  
34 - $data = $googleService->googleSearch($domain,$this->param['search']); 34 + //查询详情数据
  35 + $searchDetailModel = new GoogleSearchDetail();
  36 + $this->map['project_id']= $this->user['project_id'];
  37 + $data = $searchDetailModel->lists($this->map,$this->page,$this->row);
35 $this->response('success',Code::SUCCESS,$data); 38 $this->response('success',Code::SUCCESS,$data);
36 } 39 }
37 } 40 }
@@ -20,6 +20,7 @@ class NoticeLog extends Base @@ -20,6 +20,7 @@ class NoticeLog extends Base
20 const DELETE_NEWS_CATEGORY = 'delete_news_category'; 20 const DELETE_NEWS_CATEGORY = 'delete_news_category';
21 const DELETE_CUSTOM_CATEGORY = 'delete_custom_category'; 21 const DELETE_CUSTOM_CATEGORY = 'delete_custom_category';
22 const GENERATE_PAGE = 'generate_page';//生成页面单独改为守护进程 22 const GENERATE_PAGE = 'generate_page';//生成页面单独改为守护进程
  23 + const GOOGLE_SEARCH = 'google_search';//google搜索任务date
23 const STATUS_PENDING = 0; 24 const STATUS_PENDING = 0;
24 const STATUS_SUCCESS = 1; 25 const STATUS_SUCCESS = 1;
25 const STATUS_FAIL = 2; 26 const STATUS_FAIL = 2;
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GoogleSearch.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/3/31 13:36
  8 + */
  9 +
  10 +namespace App\Models\GoogleSearch;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +class GoogleSearch extends Base
  15 +{
  16 + protected $table = 'gl_google_search';
  17 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GoogleSearchDetail.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/3/31 13:40
  8 + */
  9 +
  10 +namespace App\Models\GoogleSearch;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +class GoogleSearchDetail extends Base
  15 +{
  16 + protected $table = 'gl_google_search_detail';
  17 +}
@@ -74,7 +74,6 @@ class GoogleSearchService @@ -74,7 +74,6 @@ class GoogleSearchService
74 $err = curl_error($curl); 74 $err = curl_error($curl);
75 curl_close($curl); 75 curl_close($curl);
76 if ($err) { 76 if ($err) {
77 - errorLog("热门关键词cURL Error #:", $url, $err);  
78 return false; 77 return false;
79 } else { 78 } else {
80 return json_decode($response,true); 79 return json_decode($response,true);
@@ -90,24 +89,13 @@ class GoogleSearchService @@ -90,24 +89,13 @@ class GoogleSearchService
90 * @param :date,query,page,device,country/时间、聚合、前页、设备、国家 89 * @param :date,query,page,device,country/时间、聚合、前页、设备、国家
91 */ 90 */
92 public function googleSearch($domain,$search){ 91 public function googleSearch($domain,$search){
93 - $data = [  
94 - 1=>'date',  
95 - 2=>'query',  
96 - 3=>'page',  
97 - 4=>'device',  
98 - 5=>'country'  
99 - ];  
100 $this->url = 'https://www.cmer.site/api/google/search'; 92 $this->url = 'https://www.cmer.site/api/google/search';
101 - $url = $this->url.'?domain='.$domain.'&q='.$data[$search]; 93 + $url = $this->url.'?domain='.$domain.'&q='.$search;
102 $data = http_get($url); 94 $data = http_get($url);
103 - $data = $data['data'] ?? [];  
104 - if(!empty($data) && ($search == 5)){  
105 - foreach ($data as $key => $val){  
106 - $val['keys_country'] = Country::getCountryNameByAlpha3(strtoupper($val['keys'][0]));  
107 - $data[$key] = $val;  
108 - } 95 + if(!isset($data['status']) || $data['status'] != 200){
  96 + return [];
109 } 97 }
  98 + $data = $data['data'] ?? [];
110 return $data; 99 return $data;
111 } 100 }
112 -  
113 } 101 }
@@ -698,11 +698,11 @@ Route::middleware(['bloginauth'])->group(function () { @@ -698,11 +698,11 @@ Route::middleware(['bloginauth'])->group(function () {
698 698
699 //google数据洞察 699 //google数据洞察
700 Route::prefix('google_keyword_insight')->group(function () { 700 Route::prefix('google_keyword_insight')->group(function () {
701 - Route::any('/getKeywordInsight', [\App\Http\Controllers\Bside\GoogleKeywordInsight\GoogleKeywordInsightController::class, 'getKeywordInsight'])->name('google_keyword_insight_getKeywordInsight'); 701 + Route::any('/getKeywordInsight', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleKeywordInsightController::class, 'getKeywordInsight'])->name('google_keyword_insight_getKeywordInsight');
702 }); 702 });
703 //google搜索数据 703 //google搜索数据
704 Route::prefix('google_search')->group(function () { 704 Route::prefix('google_search')->group(function () {
705 - Route::any('/getSearchList', [\App\Http\Controllers\Bside\GoogleKeywordInsight\GoogleSearchController::class, 'getSearchList'])->name('google_search_getSearchList'); 705 + Route::any('/getSearchList', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleSearchController::class, 'getSearchList'])->name('google_search_getSearchList');
706 }); 706 });
707 //企业产品库 707 //企业产品库
708 Route::prefix('enterprise_product')->group(function () { 708 Route::prefix('enterprise_product')->group(function () {