作者 赵彬吉
<?php
/**
* @remark :
* @name :GoogleSearchKeyword.php
* @author :lyh
* @method :post
* @time :2025/3/31 11:29
*/
namespace App\Console\Commands\GoogleSearch;
use App\Models\Com\NoticeLog;
use App\Models\Domain\DomainInfo;
use App\Models\GoogleSearch\GoogleSearch;
use App\Models\GoogleSearch\GoogleSearchDetail;
use App\Models\Project\Project;
use App\Services\GoogleSearchService;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* @remark :客户搜索词
* @name :GoogleSearchKeyword
* @author :lyh
* @method :post
* @time :2025/3/31 11:29
*/
class GoogleSearchKeyword extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'search_keyword';
/**
* The console command description.
*
* @var string
*/
protected $description = 'google搜索词';
public $googleService;
public $searchModel;
public $detailModel;
public function __construct()
{
$this->googleService = new GoogleSearchService();
$this->searchModel = new GoogleSearch();
$this->detailModel = new GoogleSearchDetail();
parent::__construct();
}
/**
* @remark :拉取google搜索数据
* @name :handle
* @author :lyh
* @method :post
* @time :2025/3/31 11:37
*/
public function handle(){
$projectModel = new Project();
$lists = $projectModel->list(['delete_status' => 0,'type'=>['!=',$projectModel::TYPE_ONE]], 'id', ['id']);
$domainModel = new DomainInfo();
foreach ($lists as $val) {
echo date('Y-m-d H:i:s') . '开始--项目的id:'. $val['id'] . PHP_EOL;
$domainInfo = $domainModel->read(['project_id'=>$val['id']]);
if($domainInfo === false){
echo '域名不存在。'.PHP_EOL;
continue;
}
$typeData = [1=>'date', 2=>'query', 3=>'page', 4=>'device', 5=>'country'];
foreach ($typeData as $keyT => $valT){
$this->_action($domainInfo['domain'],$valT,$val['id']);
}
}
return true;
}
/**
* @remark :执行的方法
* @name :_action
* @author :lyh
* @method :post
* @time :2025/3/31 11:30
*/
public function _action($domain,$type,$project_id){
$data = $this->googleService->googleSearch($domain,$type);
if(empty($data)){
echo '域名:'.$domain.'拉取数据为空.'.PHP_EOL;
return false;
}
//保存一条主记录诗句
$this->searchModel->addReturnId(['date'=>date('Y-m-d'),'project_id'=>$project_id,'type'=>$type]);
$saveData = [];
$clicksNum = array_sum(array_column($data, 'clicks'));
$impressionsNum = array_sum(array_column($data, 'impressions'));
echo 'clicksNum:'.$clicksNum.PHP_EOL;
echo 'impressionsNum:'.$impressionsNum.PHP_EOL;
foreach ($data as $val){
$saveData[] = [
'date'=>date('Y-m-d'),
'project_id'=>$project_id,
'type'=>$type,
'keys'=>$val['keys'][0],
'clicks'=>$val['clicks'],
'click_rate'=>number_format($val['clicks'] / (($clicksNum == 0) ? 1 : $clicksNum), 2),
'impressions'=>$val['impressions'],
'impressions_rate'=>number_format($val['impressions'] / (($impressionsNum == 0) ? 1 : $impressionsNum), 2),
'ctr'=>$val['ctr'],
'position'=>$val['position'],
];
}
if(!empty($saveData)){
DB::beginTransaction();
try {
//清空以前的数据
$this->detailModel->del(['project_id'=>$project_id,'type'=>$type]);
$this->detailModel->insertAll($saveData);
DB::commit();
}catch (\Exception $e){
DB::rollBack();
echo '重新添加数据失败:project_id'.$project_id.PHP_EOL;
}
}
return true;
}
}
... ...
... ... @@ -39,7 +39,6 @@ class Kernel extends ConsoleKernel
$schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1);
// 优化预设关键词 同步 20点会开始TDK生成
$schedule->command('optimize_set_keyword_sync')->dailyAt('20:00')->withoutOverlapping(1);
$schedule->command('after_count')->dailyAt('01:00')->withoutOverlapping(1); //售后日统计 每天统计一次
}
/**
... ...
... ... @@ -555,20 +555,23 @@ class OptimizeController extends BaseController
], [
'project_id.required' => '项目id不能为空',
]);
$domainModel = new DomainInfo();
$domainInfo = $domainModel->read(['project_id'=>$this->param['project_id']],['domain']);
if($domainInfo === false){
$this->response('success');
}
ProjectServer::useProject($this->param['project_id']);
$aiBlogModel = new AiBlog();
$list = $aiBlogModel->formatQuery(['route'=>['!=',null]])->pluck('route')->toArray();
$list = $aiBlogModel->list(['route'=>['!=',null]],'id',['route','new_title']);
$resultData = [];
if(!empty($list)){
$domainModel = new DomainInfo();
$DomainInfo = $domainModel->read(['project_id'=>$this->param['project_id']]);
$DomainInfo['domain'] = $DomainInfo['domain'] ?? '';
foreach ($list as $k => $v){
$v = ('https://'.$DomainInfo['domain'].'/') . 'blog/' . $v;
$list[$k] = $v;
foreach ($list as $v){
$resultData[] = ('https://'.$DomainInfo['domain'].'/') . 'blog/' . $v['route'] . '/{' . $v['new_title'] . '}';
}
}
DB::disconnect('custom_mysql');
$this->response('success',Code::SUCCESS,$list);
$this->response('success',Code::SUCCESS,$resultData);
}
/**
... ...
... ... @@ -7,7 +7,7 @@
* @time :2025/3/25 14:23
*/
namespace App\Http\Controllers\Bside\GoogleKeywordInsight;
namespace App\Http\Controllers\Bside\GoogleKeyword;
use App\Enums\Common\Code;
use App\Http\Controllers\Bside\BaseController;
... ...
... ... @@ -7,10 +7,13 @@
* @time :2025/3/27 13:53
*/
namespace App\Http\Controllers\Bside\GoogleKeywordInsight;
namespace App\Http\Controllers\Bside\GoogleKeyword;
use App\Enums\Common\Code;
use App\Http\Controllers\Bside\BaseController;
use App\Models\Com\NoticeLog;
use App\Models\GoogleSearch\GoogleSearch;
use App\Models\GoogleSearch\GoogleSearchDetail;
use App\Services\GoogleSearchService;
class GoogleSearchController extends BaseController
... ... @@ -24,14 +27,14 @@ class GoogleSearchController extends BaseController
*/
public function getSearchList(){
$this->request->validate([
'search' => 'required'
'type' => 'required'
],[
'search.required' => '搜索类型不能为空',
'type.required' => '搜索类型不能为空',
]);
//获取当前项目域名
$domain = parse_url($this->user['domain'], PHP_URL_HOST);
$googleService = new GoogleSearchService();
$data = $googleService->googleSearch($domain,$this->param['search']);
//查询详情数据
$searchDetailModel = new GoogleSearchDetail();
$this->map['project_id']= $this->user['project_id'];
$data = $searchDetailModel->lists($this->map,$this->page,$this->row);
$this->response('success',Code::SUCCESS,$data);
}
}
... ...
... ... @@ -20,6 +20,7 @@ class NoticeLog extends Base
const DELETE_NEWS_CATEGORY = 'delete_news_category';
const DELETE_CUSTOM_CATEGORY = 'delete_custom_category';
const GENERATE_PAGE = 'generate_page';//生成页面单独改为守护进程
const GOOGLE_SEARCH = 'google_search';//google搜索任务date
const STATUS_PENDING = 0;
const STATUS_SUCCESS = 1;
const STATUS_FAIL = 2;
... ...
<?php
/**
* @remark :
* @name :GoogleSearch.php
* @author :lyh
* @method :post
* @time :2025/3/31 13:36
*/
namespace App\Models\GoogleSearch;
use App\Models\Base;
class GoogleSearch extends Base
{
protected $table = 'gl_google_search';
}
... ...
<?php
/**
* @remark :
* @name :GoogleSearchDetail.php
* @author :lyh
* @method :post
* @time :2025/3/31 13:40
*/
namespace App\Models\GoogleSearch;
use App\Models\Base;
class GoogleSearchDetail extends Base
{
protected $table = 'gl_google_search_detail';
}
... ...
... ... @@ -74,7 +74,6 @@ class GoogleSearchService
$err = curl_error($curl);
curl_close($curl);
if ($err) {
errorLog("热门关键词cURL Error #:", $url, $err);
return false;
} else {
return json_decode($response,true);
... ... @@ -90,24 +89,13 @@ class GoogleSearchService
* @param :date,query,page,device,country/时间、聚合、前页、设备、国家
*/
public function googleSearch($domain,$search){
$data = [
1=>'date',
2=>'query',
3=>'page',
4=>'device',
5=>'country'
];
$this->url = 'https://www.cmer.site/api/google/search';
$url = $this->url.'?domain='.$domain.'&q='.$data[$search];
$url = $this->url.'?domain='.$domain.'&q='.$search;
$data = http_get($url);
$data = $data['data'] ?? [];
if(!empty($data) && ($search == 5)){
foreach ($data as $key => $val){
$val['keys_country'] = Country::getCountryNameByAlpha3(strtoupper($val['keys'][0]));
$data[$key] = $val;
}
if(!isset($data['status']) || $data['status'] != 200){
return [];
}
$data = $data['data'] ?? [];
return $data;
}
}
... ...
... ... @@ -698,11 +698,11 @@ Route::middleware(['bloginauth'])->group(function () {
//google数据洞察
Route::prefix('google_keyword_insight')->group(function () {
Route::any('/getKeywordInsight', [\App\Http\Controllers\Bside\GoogleKeywordInsight\GoogleKeywordInsightController::class, 'getKeywordInsight'])->name('google_keyword_insight_getKeywordInsight');
Route::any('/getKeywordInsight', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleKeywordInsightController::class, 'getKeywordInsight'])->name('google_keyword_insight_getKeywordInsight');
});
//google搜索数据
Route::prefix('google_search')->group(function () {
Route::any('/getSearchList', [\App\Http\Controllers\Bside\GoogleKeywordInsight\GoogleSearchController::class, 'getSearchList'])->name('google_search_getSearchList');
Route::any('/getSearchList', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleSearchController::class, 'getSearchList'])->name('google_search_getSearchList');
});
//企业产品库
Route::prefix('enterprise_product')->group(function () {
... ...