作者 lyh

Merge branch 'dev' of http://47.244.231.31:8099/zhl/globalso-v6 into dev

... ... @@ -48,7 +48,7 @@ class RankData extends BaseCommands
foreach ($list as $item){
$model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '')->first();
if (!$model || $model->updated_date == date('Y-m-d')) {
if (!$model || $model->updated_date != date('Y-m-d')) {
$res = $api->getGoogleRank($item['api_no']);
if(!$res){
$error++;
... ... @@ -63,7 +63,7 @@ class RankData extends BaseCommands
//有小语种的
if($item['minor_languages']){
$model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '<>', '')->first();
if (!$model || $model->updated_date == date('Y-m-d')) {
if (!$model || $model->updated_date != date('Y-m-d')) {
$res = $api->getGoogleRank($item['api_no'], 1);
if(!$res){
$error++;
... ... @@ -98,6 +98,7 @@ class RankData extends BaseCommands
if(!$lang){
foreach ($data as &$ranks){
ksort($ranks);
foreach ($ranks as &$rank){
//处理排名
if(!in_array($project_id, $without_project_ids)){
... ...
... ... @@ -137,4 +137,70 @@ class QuanqiusouApi
return $res;
}
/**
* 获取历史排名统计数据
* @param $api_no
* @param string $lang
* @return array|false|int|mixed|null
* @author zbj
* @date 2023/5/15
*/
public function getHistoryCount($api_no, $lang = '')
{
$key = "quanqiusou_api_history_count_{$api_no}_{$lang}_" . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$api_url = $this->url . '/google-rank/history_count.php';
$param = [
'apino' => $api_no,
];
if ($lang) {
$param['lang'] = $lang;
}
try {
$res = HttpUtils::get($api_url, $param);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 24 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取历史排名统计数据失败', [], $e);
return false;
}
}
return $res;
}
/**
* 获取小语种项目
* @return array|false|int|mixed|null
* @author zbj
* @date 2023/5/15
*/
public function getLangList()
{
$key = "quanqiusou_api_lang_list_" . date('Y-m-d');
$res = Cache::get($key);
if (!$res) {
$api_url = $this->url . '/api/index/langlist';
$param = [
'key' => '289c1fc81c89d79c04ed4fd72822948e',
];
try {
$res = HttpUtils::get($api_url, $param);
if($res){
$res = Arr::s2a($res);
Cache::put($key, $res, 2 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('获取小语种项目数据失败', [], $e);
return false;
}
}
return $res;
}
}
... ...
... ... @@ -2,8 +2,14 @@
namespace App\Http\Controllers\Bside;
use App\Helper\GoogleSpeedApi;
use App\Helper\QuanqiusouApi;
use App\Http\Logic\Aside\Project\ProjectLogic;
use App\Http\Logic\Bside\RankDataLogic;
use Illuminate\Http\Request;
use App\Models\RankData\Speed as GoogleSpeedModel;
use App\Services\BatchExportService;
use Illuminate\Support\Facades\Storage;
/**
* Class GoogleRankController
... ... @@ -20,8 +26,126 @@ class RankDataController extends BaseController
return $this->success($data);
}
/**
* 关键词排名列表
* @param RankDataLogic $logic
* @return \Illuminate\Http\JsonResponse
* @author zbj
* @date 2023/5/15
*/
public function keywords_rank_list(RankDataLogic $logic){
$data = $logic->keywords_rank_list();
return $this->success($data);
}
/**
* 刷新测速
* @param ProjectLogic $projectLogic
* @param GoogleSpeedApi $googleSpeedApi
* @return \Illuminate\Http\JsonResponse
* @throws \App\Exceptions\AsideGlobalException
* @throws \App\Exceptions\BsideGlobalException
* @author zbj
* @date 2023/5/15
*/
public function speed(ProjectLogic $projectLogic, GoogleSpeedApi $googleSpeedApi){
$project_id = $this->user['project_id'];
$project = $projectLogic->getInfo($project_id);
$domain = $project['deploy_optimize']['domain'] ?? '';
$data = $googleSpeedApi->run($domain);
if($data){
$model = GoogleSpeedModel::where('project_id', $project_id)->first();
$model->project_id = $project_id;
$model->data = $data;
$model->updated_date = date('Y-m-d');
$model->save();
}
return $this->success($data);
}
/**
* 数据导出
* @author zbj
* @date 2023/5/15
*/
public function export(RankDataLogic $logic){
$data = $logic->keywords_rank_list(true);
foreach ($data as &$item){
$item['domain'] = explode(':', $item['domain'])[1];
$item['lang'] = $this->request['lang'] ?: 'en';
$item['g_text'] = $item['g'] == 1 ? '主关键词' : '拓展关键词';
foreach ($item['position'] as $date => $position){
$item[$date] = $position;
}
}
$map = [
'keyword' => '关键词',
'domain' => '排名网址',
'lang' => '语言',
'g_text' => '关键词类型',
];
foreach ($data[0]['position'] as $date => $position){
$map[$date] = $date;
}
//生成文件,发送到客户端
$table = new BatchExportService("关键词数据导出");
$file = $table->head($map)->data($data)->save();
if (!$file) {
throw new \Exception('文件生成失败,请重试');
}
$fileurl = Storage::disk('runtime')->url($file);
// return Storage::disk('runtime')->download($file); //直接下载
return $this->success(['url' => $fileurl]);
}
/**
* 数据导出
* @author zbj
* @date 2023/5/15
*/
public function export_history(RankDataLogic $logic, ProjectLogic $projectLogic, QuanqiusouApi $quanqiusouApi){
$project_id = $this->user['project_id'];
$project = $projectLogic->getInfo($project_id);
$lang = $this->request['lang'] ??'';
$data = $quanqiusouApi->getHistoryCount($project['deploy_optimize']['api_no'], $lang);
if($lang){
foreach ($data['data'] as &$item){
$item['c_date'] = date("Y-m-d",strtotime($item['c_date'] . ' +1day'));
$item['reach'] = $item['home_cnt'] >= $data['bz_count'] ? '是' : '否';
}
$map = [
'c_date' => '日期',
'home_cnt' => '第一页',
'reach' => '是否达标',
];
}else{
foreach ($data['data'] as &$item){
$item['c_date'] = date("Y-m-d",strtotime($item['c_date'] . ' +1day'));
$item['reach'] = $item['cnt_home'] >= $project['deploy_build']['keyword_num'] ? '是' : '否';
}
$map = [
'c_date' => '日期',
'cnt_first' => '排名第一',
'cnt_home' => '第一页',
'cnt_thirty' => '前三页',
'cnt_fifty' => '前五页',
'cnt_hundred' => '前十页',
'reach' => '是否达标',
];
}
//生成文件,发送到客户端
$table = new BatchExportService($lang . "关键词历史数据导出");
$file = $table->head($map)->data($data['data'])->save();
if (!$file) {
throw new \Exception('文件生成失败,请重试');
}
$fileurl = Storage::disk('runtime')->url($file);
// return Storage::disk('runtime')->download($file); //直接下载
return $this->success(['url' => $fileurl]);
}
}
... ...
<?php
namespace App\Http\Logic\Aside\Project;
use App\Http\Logic\Aside\BaseLogic;
use App\Models\Project\DomainInfo;
use App\Models\Project\Payment;
use MongoDB\Client;
class DomainInfoLogic extends BaseLogic
{
public function __construct()
{
parent::__construct();
$this->model = new DomainInfo();
}
public function getDomainInfo($project_id)
{
$project = app(ProjectLogic::class)->getInfo($project_id);
$domain = $project['deploy_optimize']['domain'];
$info = $this->model->where('project_id', $project_id)->first();
//不存在或时间过期了 重新获取信息
$expiration_date = $info['domain_info']['expiration_date'] ?? '';
$end_time = $info['ssl']['end_time'] ?? '';
if(!$info || $expiration_date < date("Y-m-d") || $end_time < date('Y-m-d')){
try {
$mongo = new Client("mongodb://root:globalso8837840@23.228.125.2:27017");
$db = $mongo->globalso_monitor;
$collection = $db->project_v1;
$project_zk = $collection->findOne(['main_url' => $domain]);
$info['domain'] = $domain;
$info['domain_info'] = (array) $project_zk['domain_info'] ?? [];
$info['ssl'] = (array) $project_zk['ssl'] ?? [];
parent::save($info);
}catch (\Exception $e){
return [];
}
}
return $info;
}
}
... ...
... ... @@ -5,6 +5,7 @@ namespace App\Http\Logic\Bside;
use App\Helper\Arr;
use App\Helper\Translate;
use App\Http\Logic\Aside\Project\DomainInfoLogic;
use App\Http\Logic\Aside\Project\ProjectLogic;
use App\Models\RankData\ExternalLinks;
use App\Models\RankData\IndexedPages;
... ... @@ -12,6 +13,9 @@ use App\Models\RankData\RankData;
use App\Models\RankData\RankWeek;
use App\Models\RankData\RecommDomain;
use App\Models\RankData\Speed;
use App\Utils\HttpUtils;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
class RankDataLogic extends BaseLogic
... ... @@ -28,6 +32,7 @@ class RankDataLogic extends BaseLogic
//查数据
$project = app(ProjectLogic::class)->getInfo($project_id);
$domain_info = app(DomainInfoLogic::class)->getDomainInfo($project_id);
$rank = RankData::where('project_id', $project_id)->first();
$rank_week = RankWeek::where('project_id', $project_id)->first();
$recomm_domain = RecommDomain::where('project_id', $project_id)->first();
... ... @@ -48,7 +53,7 @@ class RankDataLogic extends BaseLogic
//小语种列表
$langs = Arr::pluck($project['deploy_optimize']['minor_languages'], 'tl');
foreach ($langs as $lang){
foreach ($langs as $lang) {
$data['langs'][$lang] = Translate::getTls($lang);
}
... ... @@ -56,8 +61,8 @@ class RankDataLogic extends BaseLogic
$data['project'] = [
'company' => $project['company'],
'domain' => $project['deploy_optimize']['domain'],
'domain_info' => '',
'cert_info' => '',
'domain_info' => ($domain_info['domain_info']['creation_date'] ?? '') . ' - ' . ($domain_info['domain_info']['expiration_date'] ?? ''),
'cert_info' => ($domain_info['ssl']['start_time'] ?? '') . ' - ' . ($domain_info['ssl']['end_time'] ?? ''),
'plan' => str_replace('营销大师-', '全球搜-', $project['deploy_build']['plan'][0]),
'keyword_num' => $project['deploy_build']['keyword_num'],
'compliance_day' => $rank['compliance_day'] ?? 0,
... ... @@ -96,7 +101,7 @@ class RankDataLogic extends BaseLogic
'data' => array_values($indexed_pages['data'] ?? []),
];
//收录数加上当日数据
if((Arr::last($data['indexed_pages_chat']['labels'])) != date('Y-m-d')){
if ((Arr::last($data['indexed_pages_chat']['labels'])) != date('Y-m-d')) {
$data['indexed_pages_chat']['labels'][] = date('Y-m-d');
$data['indexed_pages_chat']['data'][] = $data['indexed_pages_num'];
}
... ... @@ -114,7 +119,209 @@ class RankDataLogic extends BaseLogic
* @author zbj
* @date 2023/5/12
*/
public function keywords_rank_list(){
$lang = $this->request['lang'];
public function keywords_rank_list($export = false)
{
$page = intval($this->request['page'] ?: 1);
$lang = $this->request['lang'] ?: '';
$project_id = $this->user['project_id'];
$project = app(ProjectLogic::class)->getInfo($project_id);
$api_no = $project['deploy_optimize']['api_no'] ?? '';
$domain = $project['deploy_optimize']['domain'] ?? '';
$domain_arr = parse_url($domain);
$domain = $domain_arr['host'] ?? $domain_arr['path'];
//复制站点域名
$ext_projects = $this->getExtendProjects();
$flg_ext = $this->getExtFlag($ext_projects, $domain, $api_no);
$ext_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['ext'] ?? '');
//AI站点域名
$ai_projects = $this->getAiProjects()['data'] ?? [];
$flg_ai = $this->getAiFlag($ai_projects, $domain);
$ai_domain = str_replace('www.', '', $this->getAiProjects($domain)['domain'] ?? '');
$list = RankData::where('project_id', $project_id)->where('lang', $lang)->value('data');
$list30 = []; //排名前三十的
$list30_0 = []; //排名前三十且近三天没有排名的
$list100 = []; //排名前100的
$list0 = [];//排名为0的
foreach ($list as $key => $v) {
$last = Arr::last($v);
$data = [];
//处理日期
foreach ($v as $date => $position) {
$data[date('m-d', strtotime($date . '+ 1 day'))] = $position['position'];
}
//域名类型
$domain_text = '主域名:' . str_replace('www.', '', $domain);
if (!empty($last['r'])) {
$domain_text = 'AI域名:' . $last['r'];
if (in_array($flg_ext, [1, 2]) || $flg_ai == 1) {
if ($last['r'] == $ai_domain) {
$domain_text = '星链域名:' . $ai_domain;
} else if ($last['r'] == $ext_domain) {
$domain_text = '主域名2:' . $ext_domain;
} else {
$domain_text = 'AI域名:' . $last['r'];
}
}
}
$v = [
'keyword' => $key,
'domain' => $domain_text,
'g' => $last['g'], //1核心关键词
'position' => $data
];
if ($last['position'] == 0) {
$list0[] = $v;
} elseif ($last['position'] <= 30) {
if (($v['position'][date('m-d', strtotime('-1day'))] ?? '') == 0 ||
($v['position'][date('m-d', strtotime('-2day'))] ?? '') == 0) {
$list30_0[] = $v;
} else {
$list30[] = $v;
}
} else {
$list100[] = $v;
}
}
//排序 排名前30的 按关键词长短排序 最近三天无排名的排后; 后30名的按排名排序
$list30 = collect($list30)->sortBy(function ($item) {
return strlen($item['keyword']);
})->values()->all();
$list30_0 = collect($list30_0)->sortBy(function ($item) {
return strlen($item['keyword']);
})->values()->all();
$list100 = collect($list100)->sortBy(function ($item) {
return Arr::last($item['position']);
})->values()->all();
$list = collect($list30)->merge($list30_0)->merge($list100)->merge($list0)->filter(function ($item) {
//搜索
if ($this->request['search']) {
return strpos($item['keyword'], $this->request['search']) !== false;
}
//前几名
if ($this->request['first']) {
$position = Arr::last($item['position']);
return $position > 0 && $position <= $this->request['first'];
}
//核心词
if ($this->request['g']) {
return $item['g'] == $this->request['g'];
}
return true;
})->values();
if($export){
return $list->toArray();
}
$data = [
"list" => $list->forPage($page, 100)->toArray(),
"total" => $list->count(),
"page" => $page,
"total_page" => ceil($list->count() / 100),
"size" => 100
];
return $this->success($data);
}
/**
* 获取复制站点项目
* @author zbj
* @date 2023/5/12
*/
public function getExtendProjects($api_no = null)
{
$key = 'extend_projects_list';
$data = Cache::get($key);
if (!$data) {
$api_url = 'http://api.quanqiusou.cn/google-rank/api/extend_projects.php';
try {
$data = HttpUtils::get($api_url, []);
if ($data) {
$data = Arr::s2a($data);
Cache::put($key, $data, 4 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('复制站点项目获取失败', [], $e);
return false;
}
}
if ($api_no !== null) {
$data = collect($data)->where('apino', $api_no)->first();
return $data ?: [];
}
return $data;
}
/**
* 获取AI站点项目
* @author zbj
* @date 2023/5/12
*/
public function getAiProjects($domain = null)
{
$key = 'ai_projects_list';
$data = Cache::get($key);
if (!$data) {
$api_url = 'https://demosite5.globalso.com/api/domain';
try {
$data = HttpUtils::get($api_url, []);
if ($data) {
$data = Arr::s2a($data);
Cache::put($key, $data, 4 * 3600);
}
} catch (\Exception | GuzzleException $e) {
errorLog('AI站点项目获取失败', [], $e);
return false;
}
}
if ($domain !== null) {
$domain = parse_url($domain);
$data = collect($data['data'])->where('bind_domain', $domain['host'] ?? $domain['path'])->first();
return $data ?: [];
}
return $data;
}
/**
* 获取复制项目标识
* @author zbj
* @date 2023/5/15
*/
protected function getExtFlag($ext_projects, $domain, $api_no)
{
//复制站点标识
$flg_ext = 0;
if ($ext_projects) {
$ext_urls = array_column($ext_projects, 'ext');
$api_nos = array_column($ext_projects, 'apino');
if (in_array($api_no, $api_nos)) {
$flg_ext = 1;
}
if (in_array($domain, $ext_urls)) {
$flg_ext = 2;
}
}
return $flg_ext;
}
/**
* 获取AI项目标识
* @author zbj
* @date 2023/5/15
*/
protected function getAiFlag($ai_projects, $domain)
{
$flg_ai = 0;
foreach ($ai_projects as $ai_project) {
if ($ai_project['bind_domain'] == $domain) {
$flg_ai = 1;
}
}
return $flg_ai;
}
}
... ...
<?php
namespace App\Models\Project;
use App\Helper\Arr;
use App\Models\Base;
use App\Models\Devops\ServerConfig;
use Illuminate\Support\Facades\Cache;
class DomainInfo extends Base
{
//设置关联表名
protected $table = 'gl_project_domain_info';
public function setDomainInfoAttribute($value){
$this->attributes['domain_info'] = Arr::a2s($value);
}
public function getDomainInfoAttribute($value){
return Arr::s2a($value);
}
public function setSslAttribute($value){
$this->attributes['ssl'] = Arr::a2s($value);
}
public function getSslAttribute($value){
return Arr::s2a($value);
}
}
... ...
... ... @@ -14,6 +14,7 @@
"laravel/framework": "^8.75",
"laravel/sanctum": "^2.11",
"laravel/tinker": "^2.5",
"mongodb/mongodb": "^1.6",
"phpoffice/phpspreadsheet": "^1.28"
},
"require-dev": {
... ...
... ... @@ -254,6 +254,9 @@ Route::middleware(['bloginauth'])->group(function () {
Route::prefix('rank_data')->group(function () {
Route::any('/index', [\App\Http\Controllers\Bside\RankDataController::class, 'index'])->name('rank_data');
Route::any('/keywords_rank_list', [\App\Http\Controllers\Bside\RankDataController::class, 'keywords_rank_list'])->name('rank_data_keywords_rank_list');
Route::any('/speed', [\App\Http\Controllers\Bside\RankDataController::class, 'speed'])->name('rank_data_speed');
Route::any('/export', [\App\Http\Controllers\Bside\RankDataController::class, 'export'])->name('rank_data_export');
Route::any('/export_history', [\App\Http\Controllers\Bside\RankDataController::class, 'export_history'])->name('rank_data_export_history');
});
... ...