redis-queue消息队列
This commit is contained in:
parent
bca78b8923
commit
cf23c31975
@ -129,8 +129,11 @@ class OAuthController
|
||||
|
||||
public function testRefreshToken(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
// dump($options);
|
||||
return $this->googleOAuthService->queue($options);
|
||||
|
||||
return $this->successResponse([],$request);
|
||||
// return $this->successResponse([],$request);
|
||||
|
||||
//发布事件
|
||||
// $dayBeforeYesterdayStart = date('Y-m-d', strtotime('-2 day'));
|
||||
|
@ -8,12 +8,11 @@ use Google\ApiCore\ApiException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use support\Db;
|
||||
use support\Request;
|
||||
use Webman\RedisQueue\Redis;
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
|
||||
//use QL\QueryList;
|
||||
use support\Redis;
|
||||
|
||||
|
||||
class GoogleAdsAds
|
||||
@ -26,244 +25,35 @@ class GoogleAdsAds
|
||||
private $googleOAuthService;
|
||||
|
||||
|
||||
//微博热榜地址
|
||||
// const url = 'https://library.tiktok.com/api/v1/search?region=GB&type=1&start_time=1666540800&end_time=1666627200';
|
||||
|
||||
const userAgent = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||||
|
||||
const type = 'googleadsads';
|
||||
const limit = 12;
|
||||
const sort_order = 'impression,desc';
|
||||
const event = 'googleads:ads:event';
|
||||
const queue = 'googleads:ads:queue';
|
||||
|
||||
|
||||
// const countries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE","IT", "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "CH", "TR", "GB"] ;
|
||||
const countries = ["GB", "BE"];
|
||||
|
||||
|
||||
public function listAds(Request $request)
|
||||
public function syncAds()
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getAds($options);
|
||||
$queue = self::queue;
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
if ($customer['login_customer_id'] > 0) {
|
||||
Redis::send($queue, $customer);
|
||||
}
|
||||
}
|
||||
return 'ads redis queue ok';
|
||||
}
|
||||
|
||||
/**
|
||||
* get groups
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getAds($options)
|
||||
public function getAds($customer)
|
||||
{
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
$googleAdsAdService = new GoogleAdsAdService($customer['customer_id']);
|
||||
if ($customer['login_customer_id'] >0){
|
||||
$resourceName = $googleAdsAdService->runListAds($customer['customer_id'],$customer);
|
||||
}
|
||||
|
||||
$googleAdsAdService = new GoogleAdsAdService($customer['customer_id']);
|
||||
if ($customer['login_customer_id'] > 0) {
|
||||
$resourceName = $googleAdsAdService->runListAds($customer['customer_id'], $customer);
|
||||
}
|
||||
|
||||
// return $this->successResponse(['ads_list' => $resourceName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天爬取tiktok广告
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
try {
|
||||
|
||||
$client = new Client([
|
||||
//允许重定向
|
||||
// 'allow_redirects' => true,
|
||||
]);
|
||||
|
||||
|
||||
// 获取前两天 0 点的时间戳
|
||||
$dayBeforeYesterdayStart = strtotime('-2 days 00:00:00');
|
||||
|
||||
// 获取前一天 0 点的时间戳
|
||||
$yesterdayStart = strtotime('-1 day 00:00:00');
|
||||
$countryCache = Redis::get(self::type . 'lastCountry');
|
||||
//全部跑完跳出
|
||||
if ($countryCache == 'All') {
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($countryCache)) {
|
||||
$countryCache = 'GB';
|
||||
}
|
||||
|
||||
$searchIdCache = Redis::get(self::type . 'lastSearchId');
|
||||
$offsetCache = Redis::get(self::type . 'nextOffset');
|
||||
$totalCache = Redis::get(self::type . 'totalCache');
|
||||
if (!isset($searchIdCache) || empty($searchIdCache)) {
|
||||
$searchIdCache = '';
|
||||
}
|
||||
if (!isset($offsetCache) || empty($searchIdCache)) {
|
||||
$offsetCache = 0;
|
||||
}
|
||||
if (!isset($totalCache) || empty($searchIdCache)) {
|
||||
$totalCache = 0;
|
||||
}
|
||||
|
||||
//判断国家是否跑完。
|
||||
if ($totalCache > 0 && $offsetCache > ceil($totalCache / self::limit)) {
|
||||
$key = array_search($countryCache, self::countries, true);
|
||||
if (in_array($countryCache, self::countries) && isset(self::countries[$key + 1])) {
|
||||
$countryCache = self::countries[$key + 1];
|
||||
dump('更新' . $countryCache . '国家的tiktok Ads 完成');
|
||||
} else {
|
||||
$countryCache = 'All'; //赋值非正常国家的code中断定时任务
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$start_time = $dayBeforeYesterdayStart;
|
||||
$end_time = $yesterdayStart;
|
||||
//当前国家爬取
|
||||
$currentParams = null;
|
||||
$currentParams = ['country' => $countryCache, 'search_id' => $searchIdCache, 'type' => 1, 'start_time' => $start_time, 'end_time' => $end_time];
|
||||
|
||||
|
||||
$url = 'https://library.tiktok.com/api/v1/search?region=' . $currentParams['country'] . '&type=' . $currentParams['type'] . '&start_time=' . $currentParams['start_time'] . '&end_time=' . $currentParams['end_time'];
|
||||
|
||||
$res = json_decode($client->post($url, [
|
||||
'headers' => [
|
||||
'accept' => 'application/json, text/plain, */*',
|
||||
'accept-language' => 'zh-CN,zh;q=0.9',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'cookie: _ttp=2ov8Fc4C2CaNscHJd90O9fMhlpE; _ga=GA1.1.1025820618.1731926196; FPID=FPID2.2.Bcgkp%2Fk%2Bbn5w5YeSMR9wd9VpNHJwTUpkkaEqSdCEa0w%3D.1731926196; FPAU=1.2.944915349.1731926193; FPLC=mbVyryI5aG6IVpAvhs1JsgWjA7FVA6QsCJ7VbXhM7zWoXNp4rcD0IK7FNTTf%2FuOrqeOgqEhTd4NB3hY7q3aDVTGQa3WGHqxkGte4%2BBZxsrpaHFas9kb7DPRXM12T5Q%3D%3D; _ga_TEQXTT9FE4=GS1.1.1732097542.7.0.1732097542.0.0.857840528',
|
||||
'origin' => 'https://library.tiktok.com',
|
||||
'priority' => 'u=1, i',
|
||||
'referer' => 'https://library.tiktok.com/ads?region=AT&start_time=1731945600000&end_time=1732032000000&adv_name=&adv_biz_ids=&query_type=&sort_type=last_shown_date,desc',
|
||||
'sec-ch-ua' => '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile' => '?0',
|
||||
'sec-ch-ua-platform' => '"Windows"',
|
||||
'sec-fetch-dest' => 'empty',
|
||||
'sec-fetch-mode' => 'cors',
|
||||
'sec-fetch-site' => 'same-origin',
|
||||
'user-agent' => self::userAgent,
|
||||
// 'user-agent' => 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
],
|
||||
'json' => [
|
||||
'query' => '',
|
||||
'query_type' => '',
|
||||
'adv_biz_ids' => '',
|
||||
'order' => self::sort_order,
|
||||
'offset' => (int)$offsetCache,
|
||||
'search_id' => $currentParams['search_id'],
|
||||
'limit' => self::limit,
|
||||
],
|
||||
|
||||
])->getBody()->getContents(), true);
|
||||
// dump($res);return; //调试点
|
||||
|
||||
if ($res['search_id'] != $searchIdCache) {
|
||||
$searchIdCache = $res['search_id'];
|
||||
dump('search_id更新 ' . $searchIdCache . ' 成功');
|
||||
}
|
||||
|
||||
|
||||
if ($res['total'] == 0 || $res['code'] != 0) {
|
||||
dump('更新tiktok Ads接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
}
|
||||
$listAdsIds = [];
|
||||
foreach ($res['data'] as $ad) {
|
||||
if ($ad['audit_status'] == 2 || empty($ad['videos'])) {
|
||||
continue; //审核不过或者没视频不采集
|
||||
}
|
||||
|
||||
$imagesJson = is_array($ad['image_urls']) ? json_encode($ad['image_urls']) : json_encode([]);
|
||||
$rejection_info = is_array($ad['rejection_info']) ? json_encode($ad['rejection_info']) : null;
|
||||
// dump($rejection_info);
|
||||
$insertData[$ad['id']] = [
|
||||
'ad_id' => $ad['id'],
|
||||
'name' => $ad['name'],
|
||||
'audit_status' => $ad['audit_status'],
|
||||
'type' => $ad['type'],
|
||||
'first_shown_date' => $ad['first_shown_date'],
|
||||
'last_shown_date' => $ad['last_shown_date'],
|
||||
'image_urls' => $imagesJson,
|
||||
'estimated_audience' => $ad['estimated_audience'],
|
||||
'spent' => $ad['spent'],
|
||||
'impression' => $ad['impression'],
|
||||
'show_mode' => $ad['show_mode'],
|
||||
'rejection_info' => $rejection_info,
|
||||
'sor_audit_status' => $ad['sor_audit_status'],
|
||||
'country_code' => $countryCache,
|
||||
];
|
||||
if (isset($ad['videos']) && !empty($ad['videos'])) {
|
||||
// 遍历 "videos" 数组
|
||||
foreach ($ad['videos'] as $video) {
|
||||
$insertData[$ad['id']]['video_url'] = $video['video_url'];
|
||||
$insertData[$ad['id']]['cover_img'] = $video['cover_img'];
|
||||
}
|
||||
}
|
||||
$listAdsIds = array_column($insertData, 'ad_id');
|
||||
|
||||
}
|
||||
// dump($insertData);return;
|
||||
|
||||
|
||||
if (empty($insertData)) return;
|
||||
|
||||
//开启事务
|
||||
Db::beginTransaction();
|
||||
|
||||
|
||||
//删除原来的旧数据
|
||||
TiktokAd::query()->whereIn('ad_id', array_keys($insertData))->delete();
|
||||
//添加新的数据
|
||||
TiktokAd::query()->insert($insertData);
|
||||
|
||||
//redis缓存
|
||||
Redis::set(self::type, json_encode($insertData, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//redis缓存 记录更新时间
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Redis::set(self::type . 'time', $time);
|
||||
Redis::set(self::type . 'lastCountry', $countryCache);
|
||||
Redis::set(self::type . 'nextOffset', ++$offsetCache); //记录下一次的offset
|
||||
Redis::set(self::type . 'totalCache', $res['total']);
|
||||
Redis::set(self::type . 'lastSearchId', $searchIdCache);
|
||||
if (!empty($listAdsIds)) {
|
||||
Redis::rPush(self::type . 'AdsIds', ...$listAdsIds);
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
//销毁$res
|
||||
unset($res);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||
} catch (GuzzleException|\Exception $exception) {
|
||||
//回滚事务
|
||||
Db::rollBack();
|
||||
dump('更' . self::type . '异常:' . $exception->getMessage());
|
||||
dump($exception);
|
||||
}
|
||||
// } catch (ClientExceptionInterface $e) {
|
||||
// // 捕获 4xx 错误
|
||||
// dump( 'Client error: ' . $e->getMessage() . "\n");
|
||||
// } catch (ServerExceptionInterface $e) {
|
||||
// // 捕获 5xx 错误
|
||||
// dump('Server error: ' . $e->getMessage() . "\n");
|
||||
// } catch (TransportExceptionInterface $e) {
|
||||
// // 捕获网络传输错误
|
||||
// dump('Transport error: ' . $e->getMessage() . "\n") ;
|
||||
// } catch (\Exception $e) {
|
||||
// // 捕获所有其他错误
|
||||
// dump('General error: ' . $e->getMessage() . "\n") ;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// 可以加入一些公共方法
|
||||
protected function successResponse($data): Response
|
||||
{
|
||||
|
@ -5,15 +5,11 @@ namespace app\event;
|
||||
use app\service\GoogleAdsAssetRelationService;
|
||||
use app\service\GoogleOAuthService;
|
||||
use Google\ApiCore\ApiException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use support\Db;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
|
||||
//use QL\QueryList;
|
||||
use support\Redis;
|
||||
use Webman\RedisQueue\Redis;
|
||||
|
||||
|
||||
class GoogleAdsAssetRelations
|
||||
@ -26,258 +22,47 @@ class GoogleAdsAssetRelations
|
||||
private $googleOAuthService;
|
||||
|
||||
|
||||
//微博热榜地址
|
||||
// const url = 'https://library.tiktok.com/api/v1/search?region=GB&type=1&start_time=1666540800&end_time=1666627200';
|
||||
const event = 'googleads:assetrelations:event';
|
||||
const queue = 'googleads:assetrelations:queue';
|
||||
const video_queue = 'googleads:assetrelations:video_queue';
|
||||
|
||||
const userAgent = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||||
|
||||
const IMAGEASSET = 'googleadsassetrelations_image';
|
||||
const VIDEOASSET = 'googleadsassetrelations_video';
|
||||
const limit = 12;
|
||||
const sort_order = 'impression,desc';
|
||||
|
||||
|
||||
// const countries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE","IT", "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "CH", "TR", "GB"] ;
|
||||
const countries = ["GB", "BE"];
|
||||
|
||||
|
||||
public function listAssetRelations(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getAssetRelations($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* get asset relations
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getAssetRelations($options)
|
||||
public function syncAssetRelations()
|
||||
{
|
||||
$queue = self::queue;
|
||||
$video_queue = self::video_queue;
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
// dump($customer);
|
||||
|
||||
if ($customer['login_customer_id'] > 0) {
|
||||
$googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customer['customer_id']);
|
||||
$resourceName = $googleAdsAssetRelationService->runListAssetRelations($customer['customer_id']);
|
||||
Redis::send($queue, $customer);
|
||||
Redis::send($video_queue, $customer);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->successResponse(['ads_list' => $resourceName]);
|
||||
return 'assets redis queue ok';
|
||||
}
|
||||
|
||||
/**
|
||||
* get asset relations
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getVideoAssetRelations($options)
|
||||
public function getAssetRelations($customer)
|
||||
{
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
if ($customer['login_customer_id'] > 0) {
|
||||
$googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customer['customer_id']);
|
||||
$resourceName = $googleAdsAssetRelationService->runListVideoAssetRelations($customer['customer_id']);
|
||||
$resourceName = $googleAdsAssetRelationService->runListAssetRelations($customer['customer_id']);
|
||||
}
|
||||
|
||||
// return $this->successResponse(['ads_list' => $resourceName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天爬取tiktok广告
|
||||
* @return void
|
||||
* get asset relations
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function update()
|
||||
public function getVideoAssetRelations($customer)
|
||||
{
|
||||
try {
|
||||
$googleAdsAssetRelationService = new GoogleAdsAssetRelationService($customer['customer_id']);
|
||||
$resourceName = $googleAdsAssetRelationService->runListVideoAssetRelations($customer['customer_id']);
|
||||
|
||||
$client = new Client([
|
||||
//允许重定向
|
||||
// 'allow_redirects' => true,
|
||||
]);
|
||||
|
||||
|
||||
// 获取前两天 0 点的时间戳
|
||||
$dayBeforeYesterdayStart = strtotime('-2 days 00:00:00');
|
||||
|
||||
// 获取前一天 0 点的时间戳
|
||||
$yesterdayStart = strtotime('-1 day 00:00:00');
|
||||
$countryCache = Redis::get(self::type . 'lastCountry');
|
||||
//全部跑完跳出
|
||||
if ($countryCache == 'All') {
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($countryCache)) {
|
||||
$countryCache = 'GB';
|
||||
}
|
||||
|
||||
$searchIdCache = Redis::get(self::type . 'lastSearchId');
|
||||
$offsetCache = Redis::get(self::type . 'nextOffset');
|
||||
$totalCache = Redis::get(self::type . 'totalCache');
|
||||
if (!isset($searchIdCache) || empty($searchIdCache)) {
|
||||
$searchIdCache = '';
|
||||
}
|
||||
if (!isset($offsetCache) || empty($searchIdCache)) {
|
||||
$offsetCache = 0;
|
||||
}
|
||||
if (!isset($totalCache) || empty($searchIdCache)) {
|
||||
$totalCache = 0;
|
||||
}
|
||||
|
||||
//判断国家是否跑完。
|
||||
if ($totalCache > 0 && $offsetCache > ceil($totalCache / self::limit)) {
|
||||
$key = array_search($countryCache, self::countries, true);
|
||||
if (in_array($countryCache, self::countries) && isset(self::countries[$key + 1])) {
|
||||
$countryCache = self::countries[$key + 1];
|
||||
dump('更新' . $countryCache . '国家的tiktok Ads 完成');
|
||||
} else {
|
||||
$countryCache = 'All'; //赋值非正常国家的code中断定时任务
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$start_time = $dayBeforeYesterdayStart;
|
||||
$end_time = $yesterdayStart;
|
||||
//当前国家爬取
|
||||
$currentParams = null;
|
||||
$currentParams = ['country' => $countryCache, 'search_id' => $searchIdCache, 'type' => 1, 'start_time' => $start_time, 'end_time' => $end_time];
|
||||
|
||||
|
||||
$url = 'https://library.tiktok.com/api/v1/search?region=' . $currentParams['country'] . '&type=' . $currentParams['type'] . '&start_time=' . $currentParams['start_time'] . '&end_time=' . $currentParams['end_time'];
|
||||
|
||||
$res = json_decode($client->post($url, [
|
||||
'headers' => [
|
||||
'accept' => 'application/json, text/plain, */*',
|
||||
'accept-language' => 'zh-CN,zh;q=0.9',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'cookie: _ttp=2ov8Fc4C2CaNscHJd90O9fMhlpE; _ga=GA1.1.1025820618.1731926196; FPID=FPID2.2.Bcgkp%2Fk%2Bbn5w5YeSMR9wd9VpNHJwTUpkkaEqSdCEa0w%3D.1731926196; FPAU=1.2.944915349.1731926193; FPLC=mbVyryI5aG6IVpAvhs1JsgWjA7FVA6QsCJ7VbXhM7zWoXNp4rcD0IK7FNTTf%2FuOrqeOgqEhTd4NB3hY7q3aDVTGQa3WGHqxkGte4%2BBZxsrpaHFas9kb7DPRXM12T5Q%3D%3D; _ga_TEQXTT9FE4=GS1.1.1732097542.7.0.1732097542.0.0.857840528',
|
||||
'origin' => 'https://library.tiktok.com',
|
||||
'priority' => 'u=1, i',
|
||||
'referer' => 'https://library.tiktok.com/ads?region=AT&start_time=1731945600000&end_time=1732032000000&adv_name=&adv_biz_ids=&query_type=&sort_type=last_shown_date,desc',
|
||||
'sec-ch-ua' => '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile' => '?0',
|
||||
'sec-ch-ua-platform' => '"Windows"',
|
||||
'sec-fetch-dest' => 'empty',
|
||||
'sec-fetch-mode' => 'cors',
|
||||
'sec-fetch-site' => 'same-origin',
|
||||
'user-agent' => self::userAgent,
|
||||
// 'user-agent' => 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
],
|
||||
'json' => [
|
||||
'query' => '',
|
||||
'query_type' => '',
|
||||
'adv_biz_ids' => '',
|
||||
'order' => self::sort_order,
|
||||
'offset' => (int)$offsetCache,
|
||||
'search_id' => $currentParams['search_id'],
|
||||
'limit' => self::limit,
|
||||
],
|
||||
|
||||
])->getBody()->getContents(), true);
|
||||
// dump($res);return; //调试点
|
||||
|
||||
if ($res['search_id'] != $searchIdCache) {
|
||||
$searchIdCache = $res['search_id'];
|
||||
dump('search_id更新 ' . $searchIdCache . ' 成功');
|
||||
}
|
||||
|
||||
|
||||
if ($res['total'] == 0 || $res['code'] != 0) {
|
||||
dump('更新tiktok Ads接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
}
|
||||
$listAdsIds = [];
|
||||
foreach ($res['data'] as $ad) {
|
||||
if ($ad['audit_status'] == 2 || empty($ad['videos'])) {
|
||||
continue; //审核不过或者没视频不采集
|
||||
}
|
||||
|
||||
$imagesJson = is_array($ad['image_urls']) ? json_encode($ad['image_urls']) : json_encode([]);
|
||||
$rejection_info = is_array($ad['rejection_info']) ? json_encode($ad['rejection_info']) : null;
|
||||
// dump($rejection_info);
|
||||
$insertData[$ad['id']] = [
|
||||
'ad_id' => $ad['id'],
|
||||
'name' => $ad['name'],
|
||||
'audit_status' => $ad['audit_status'],
|
||||
'type' => $ad['type'],
|
||||
'first_shown_date' => $ad['first_shown_date'],
|
||||
'last_shown_date' => $ad['last_shown_date'],
|
||||
'image_urls' => $imagesJson,
|
||||
'estimated_audience' => $ad['estimated_audience'],
|
||||
'spent' => $ad['spent'],
|
||||
'impression' => $ad['impression'],
|
||||
'show_mode' => $ad['show_mode'],
|
||||
'rejection_info' => $rejection_info,
|
||||
'sor_audit_status' => $ad['sor_audit_status'],
|
||||
'country_code' => $countryCache,
|
||||
];
|
||||
if (isset($ad['videos']) && !empty($ad['videos'])) {
|
||||
// 遍历 "videos" 数组
|
||||
foreach ($ad['videos'] as $video) {
|
||||
$insertData[$ad['id']]['video_url'] = $video['video_url'];
|
||||
$insertData[$ad['id']]['cover_img'] = $video['cover_img'];
|
||||
}
|
||||
}
|
||||
$listAdsIds = array_column($insertData, 'ad_id');
|
||||
|
||||
}
|
||||
// dump($insertData);return;
|
||||
|
||||
|
||||
if (empty($insertData)) return;
|
||||
|
||||
//开启事务
|
||||
Db::beginTransaction();
|
||||
|
||||
|
||||
//删除原来的旧数据
|
||||
TiktokAd::query()->whereIn('ad_id', array_keys($insertData))->delete();
|
||||
//添加新的数据
|
||||
TiktokAd::query()->insert($insertData);
|
||||
|
||||
//redis缓存
|
||||
Redis::set(self::type, json_encode($insertData, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//redis缓存 记录更新时间
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Redis::set(self::type . 'time', $time);
|
||||
Redis::set(self::type . 'lastCountry', $countryCache);
|
||||
Redis::set(self::type . 'nextOffset', ++$offsetCache); //记录下一次的offset
|
||||
Redis::set(self::type . 'totalCache', $res['total']);
|
||||
Redis::set(self::type . 'lastSearchId', $searchIdCache);
|
||||
if (!empty($listAdsIds)) {
|
||||
Redis::rPush(self::type . 'AdsIds', ...$listAdsIds);
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
//销毁$res
|
||||
unset($res);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||
} catch (GuzzleException|\Exception $exception) {
|
||||
//回滚事务
|
||||
Db::rollBack();
|
||||
dump('更' . self::type . '异常:' . $exception->getMessage());
|
||||
dump($exception);
|
||||
}
|
||||
// } catch (ClientExceptionInterface $e) {
|
||||
// // 捕获 4xx 错误
|
||||
// dump( 'Client error: ' . $e->getMessage() . "\n");
|
||||
// } catch (ServerExceptionInterface $e) {
|
||||
// // 捕获 5xx 错误
|
||||
// dump('Server error: ' . $e->getMessage() . "\n");
|
||||
// } catch (TransportExceptionInterface $e) {
|
||||
// // 捕获网络传输错误
|
||||
// dump('Transport error: ' . $e->getMessage() . "\n") ;
|
||||
// } catch (\Exception $e) {
|
||||
// // 捕获所有其他错误
|
||||
// dump('General error: ' . $e->getMessage() . "\n") ;
|
||||
// }
|
||||
// return $this->successResponse(['ads_list' => $resourceName]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -8,12 +8,11 @@ use Google\ApiCore\ApiException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use support\Db;
|
||||
use support\Request;
|
||||
use Webman\RedisQueue\Redis;
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
|
||||
//use QL\QueryList;
|
||||
use support\Redis;
|
||||
|
||||
|
||||
class GoogleAdsAssets
|
||||
@ -25,245 +24,34 @@ class GoogleAdsAssets
|
||||
|
||||
private $googleOAuthService;
|
||||
|
||||
const event = 'googleads:assets:event';
|
||||
const queue = 'googleads:assets:queue';
|
||||
|
||||
//微博热榜地址
|
||||
// const url = 'https://library.tiktok.com/api/v1/search?region=GB&type=1&start_time=1666540800&end_time=1666627200';
|
||||
|
||||
const userAgent = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||||
|
||||
const type = 'googleadsassets';
|
||||
const limit = 12;
|
||||
const sort_order = 'impression,desc';
|
||||
|
||||
|
||||
// const countries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE","IT", "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "CH", "TR", "GB"] ;
|
||||
const countries = ["GB", "BE"];
|
||||
|
||||
|
||||
public function listAssets(Request $request)
|
||||
public function syncAssets()
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getAssets($options);
|
||||
$queue = self::queue;
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
if ($customer['login_customer_id'] > 0) {
|
||||
Redis::send($queue, $customer);
|
||||
}
|
||||
}
|
||||
return 'assets redis queue ok';
|
||||
}
|
||||
|
||||
/**
|
||||
* get assets
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getAssets($options)
|
||||
public function getAssets($customer)
|
||||
{
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
$googleAdsAssetService = new GoogleAdsAssetService($customer['customer_id']);
|
||||
if ($customer['login_customer_id'] >0){
|
||||
$resourceName = $googleAdsAssetService->runListAssets($customer['customer_id'],$customer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// return $this->successResponse(['ads_list' => $resourceName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天爬取tiktok广告
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
try {
|
||||
|
||||
$client = new Client([
|
||||
//允许重定向
|
||||
// 'allow_redirects' => true,
|
||||
]);
|
||||
|
||||
|
||||
// 获取前两天 0 点的时间戳
|
||||
$dayBeforeYesterdayStart = strtotime('-2 days 00:00:00');
|
||||
|
||||
// 获取前一天 0 点的时间戳
|
||||
$yesterdayStart = strtotime('-1 day 00:00:00');
|
||||
$countryCache = Redis::get(self::type . 'lastCountry');
|
||||
//全部跑完跳出
|
||||
if ($countryCache == 'All') {
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($countryCache)) {
|
||||
$countryCache = 'GB';
|
||||
}
|
||||
|
||||
$searchIdCache = Redis::get(self::type . 'lastSearchId');
|
||||
$offsetCache = Redis::get(self::type . 'nextOffset');
|
||||
$totalCache = Redis::get(self::type . 'totalCache');
|
||||
if (!isset($searchIdCache) || empty($searchIdCache)) {
|
||||
$searchIdCache = '';
|
||||
}
|
||||
if (!isset($offsetCache) || empty($searchIdCache)) {
|
||||
$offsetCache = 0;
|
||||
}
|
||||
if (!isset($totalCache) || empty($searchIdCache)) {
|
||||
$totalCache = 0;
|
||||
}
|
||||
|
||||
//判断国家是否跑完。
|
||||
if ($totalCache > 0 && $offsetCache > ceil($totalCache / self::limit)) {
|
||||
$key = array_search($countryCache, self::countries, true);
|
||||
if (in_array($countryCache, self::countries) && isset(self::countries[$key + 1])) {
|
||||
$countryCache = self::countries[$key + 1];
|
||||
dump('更新' . $countryCache . '国家的tiktok Ads 完成');
|
||||
} else {
|
||||
$countryCache = 'All'; //赋值非正常国家的code中断定时任务
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$start_time = $dayBeforeYesterdayStart;
|
||||
$end_time = $yesterdayStart;
|
||||
//当前国家爬取
|
||||
$currentParams = null;
|
||||
$currentParams = ['country' => $countryCache, 'search_id' => $searchIdCache, 'type' => 1, 'start_time' => $start_time, 'end_time' => $end_time];
|
||||
|
||||
|
||||
$url = 'https://library.tiktok.com/api/v1/search?region=' . $currentParams['country'] . '&type=' . $currentParams['type'] . '&start_time=' . $currentParams['start_time'] . '&end_time=' . $currentParams['end_time'];
|
||||
|
||||
$res = json_decode($client->post($url, [
|
||||
'headers' => [
|
||||
'accept' => 'application/json, text/plain, */*',
|
||||
'accept-language' => 'zh-CN,zh;q=0.9',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'cookie: _ttp=2ov8Fc4C2CaNscHJd90O9fMhlpE; _ga=GA1.1.1025820618.1731926196; FPID=FPID2.2.Bcgkp%2Fk%2Bbn5w5YeSMR9wd9VpNHJwTUpkkaEqSdCEa0w%3D.1731926196; FPAU=1.2.944915349.1731926193; FPLC=mbVyryI5aG6IVpAvhs1JsgWjA7FVA6QsCJ7VbXhM7zWoXNp4rcD0IK7FNTTf%2FuOrqeOgqEhTd4NB3hY7q3aDVTGQa3WGHqxkGte4%2BBZxsrpaHFas9kb7DPRXM12T5Q%3D%3D; _ga_TEQXTT9FE4=GS1.1.1732097542.7.0.1732097542.0.0.857840528',
|
||||
'origin' => 'https://library.tiktok.com',
|
||||
'priority' => 'u=1, i',
|
||||
'referer' => 'https://library.tiktok.com/ads?region=AT&start_time=1731945600000&end_time=1732032000000&adv_name=&adv_biz_ids=&query_type=&sort_type=last_shown_date,desc',
|
||||
'sec-ch-ua' => '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile' => '?0',
|
||||
'sec-ch-ua-platform' => '"Windows"',
|
||||
'sec-fetch-dest' => 'empty',
|
||||
'sec-fetch-mode' => 'cors',
|
||||
'sec-fetch-site' => 'same-origin',
|
||||
'user-agent' => self::userAgent,
|
||||
// 'user-agent' => 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
],
|
||||
'json' => [
|
||||
'query' => '',
|
||||
'query_type' => '',
|
||||
'adv_biz_ids' => '',
|
||||
'order' => self::sort_order,
|
||||
'offset' => (int)$offsetCache,
|
||||
'search_id' => $currentParams['search_id'],
|
||||
'limit' => self::limit,
|
||||
],
|
||||
|
||||
])->getBody()->getContents(), true);
|
||||
// dump($res);return; //调试点
|
||||
|
||||
if ($res['search_id'] != $searchIdCache) {
|
||||
$searchIdCache = $res['search_id'];
|
||||
dump('search_id更新 ' . $searchIdCache . ' 成功');
|
||||
}
|
||||
|
||||
|
||||
if ($res['total'] == 0 || $res['code'] != 0) {
|
||||
dump('更新tiktok Ads接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
}
|
||||
$listAdsIds = [];
|
||||
foreach ($res['data'] as $ad) {
|
||||
if ($ad['audit_status'] == 2 || empty($ad['videos'])) {
|
||||
continue; //审核不过或者没视频不采集
|
||||
}
|
||||
|
||||
$imagesJson = is_array($ad['image_urls']) ? json_encode($ad['image_urls']) : json_encode([]);
|
||||
$rejection_info = is_array($ad['rejection_info']) ? json_encode($ad['rejection_info']) : null;
|
||||
// dump($rejection_info);
|
||||
$insertData[$ad['id']] = [
|
||||
'ad_id' => $ad['id'],
|
||||
'name' => $ad['name'],
|
||||
'audit_status' => $ad['audit_status'],
|
||||
'type' => $ad['type'],
|
||||
'first_shown_date' => $ad['first_shown_date'],
|
||||
'last_shown_date' => $ad['last_shown_date'],
|
||||
'image_urls' => $imagesJson,
|
||||
'estimated_audience' => $ad['estimated_audience'],
|
||||
'spent' => $ad['spent'],
|
||||
'impression' => $ad['impression'],
|
||||
'show_mode' => $ad['show_mode'],
|
||||
'rejection_info' => $rejection_info,
|
||||
'sor_audit_status' => $ad['sor_audit_status'],
|
||||
'country_code' => $countryCache,
|
||||
];
|
||||
if (isset($ad['videos']) && !empty($ad['videos'])) {
|
||||
// 遍历 "videos" 数组
|
||||
foreach ($ad['videos'] as $video) {
|
||||
$insertData[$ad['id']]['video_url'] = $video['video_url'];
|
||||
$insertData[$ad['id']]['cover_img'] = $video['cover_img'];
|
||||
}
|
||||
}
|
||||
$listAdsIds = array_column($insertData, 'ad_id');
|
||||
|
||||
}
|
||||
// dump($insertData);return;
|
||||
|
||||
|
||||
if (empty($insertData)) return;
|
||||
|
||||
//开启事务
|
||||
Db::beginTransaction();
|
||||
|
||||
|
||||
//删除原来的旧数据
|
||||
TiktokAd::query()->whereIn('ad_id', array_keys($insertData))->delete();
|
||||
//添加新的数据
|
||||
TiktokAd::query()->insert($insertData);
|
||||
|
||||
//redis缓存
|
||||
Redis::set(self::type, json_encode($insertData, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//redis缓存 记录更新时间
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Redis::set(self::type . 'time', $time);
|
||||
Redis::set(self::type . 'lastCountry', $countryCache);
|
||||
Redis::set(self::type . 'nextOffset', ++$offsetCache); //记录下一次的offset
|
||||
Redis::set(self::type . 'totalCache', $res['total']);
|
||||
Redis::set(self::type . 'lastSearchId', $searchIdCache);
|
||||
if (!empty($listAdsIds)) {
|
||||
Redis::rPush(self::type . 'AdsIds', ...$listAdsIds);
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
//销毁$res
|
||||
unset($res);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||
} catch (GuzzleException|\Exception $exception) {
|
||||
//回滚事务
|
||||
Db::rollBack();
|
||||
dump('更' . self::type . '异常:' . $exception->getMessage());
|
||||
dump($exception);
|
||||
}
|
||||
// } catch (ClientExceptionInterface $e) {
|
||||
// // 捕获 4xx 错误
|
||||
// dump( 'Client error: ' . $e->getMessage() . "\n");
|
||||
// } catch (ServerExceptionInterface $e) {
|
||||
// // 捕获 5xx 错误
|
||||
// dump('Server error: ' . $e->getMessage() . "\n");
|
||||
// } catch (TransportExceptionInterface $e) {
|
||||
// // 捕获网络传输错误
|
||||
// dump('Transport error: ' . $e->getMessage() . "\n") ;
|
||||
// } catch (\Exception $e) {
|
||||
// // 捕获所有其他错误
|
||||
// dump('General error: ' . $e->getMessage() . "\n") ;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// 可以加入一些公共方法
|
||||
protected function successResponse($data): Response
|
||||
{
|
||||
|
@ -2,19 +2,17 @@
|
||||
|
||||
namespace app\event;
|
||||
|
||||
use app\model\Campaign;
|
||||
use app\service\GoogleAdsCampaignService;
|
||||
use app\service\GoogleOAuthService;
|
||||
use Google\ApiCore\ApiException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use support\Db;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
use Webman\RedisQueue\Redis;
|
||||
|
||||
//use QL\QueryList;
|
||||
use support\Redis;
|
||||
|
||||
|
||||
class GoogleAdsCampaigns
|
||||
@ -27,247 +25,40 @@ class GoogleAdsCampaigns
|
||||
|
||||
private $googleOAuthService;
|
||||
|
||||
const event = 'googleads:campaigns:event';
|
||||
const queue = 'googleads:campaigns:queue';
|
||||
|
||||
//微博热榜地址
|
||||
// const url = 'https://library.tiktok.com/api/v1/search?region=GB&type=1&start_time=1666540800&end_time=1666627200';
|
||||
|
||||
const userAgent = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||||
|
||||
const type = 'googleadscampaigns';
|
||||
const limit = 12;
|
||||
const sort_order = 'impression,desc';
|
||||
|
||||
|
||||
// const countries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE","IT", "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "CH", "TR", "GB"] ;
|
||||
const countries = ["GB", "BE"];
|
||||
|
||||
|
||||
|
||||
|
||||
public function listCampaigns(Request $request)
|
||||
public function syncCampaigns()
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getCampaigns($options);
|
||||
$queue = self::queue;
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
if ($customer['login_customer_id'] >0){
|
||||
Redis::send($queue,$customer);
|
||||
}
|
||||
}
|
||||
return 'redis queue ok';
|
||||
}
|
||||
|
||||
/**
|
||||
* get campaigns
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getCampaigns($options)
|
||||
public function getCampaigns($customer)
|
||||
{
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
// $customers = $this->googleOAuthService->getGoogleAdCustomers($options);
|
||||
// dump($customers);
|
||||
foreach ($customers as $customer) {
|
||||
// foreach ($customers as $customer) {
|
||||
// dump($customer);
|
||||
$googleAdsCampaignService = new googleAdsCampaignService($customer['customer_id']);
|
||||
if ($customer['login_customer_id'] >0){
|
||||
$resourceName = $googleAdsCampaignService->runListCampaigns($customer['customer_id'],$customer);
|
||||
}
|
||||
|
||||
}
|
||||
// }
|
||||
// return $this->successResponse(['campaigns_list' => $resourceName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天爬取tiktok广告
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
try {
|
||||
|
||||
$client = new Client([
|
||||
//允许重定向
|
||||
// 'allow_redirects' => true,
|
||||
]);
|
||||
|
||||
|
||||
// 获取前两天 0 点的时间戳
|
||||
$dayBeforeYesterdayStart = strtotime('-2 days 00:00:00');
|
||||
|
||||
// 获取前一天 0 点的时间戳
|
||||
$yesterdayStart = strtotime('-1 day 00:00:00');
|
||||
$countryCache = Redis::get(self::type . 'lastCountry');
|
||||
//全部跑完跳出
|
||||
if ($countryCache == 'All') {
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($countryCache)) {
|
||||
$countryCache = 'GB';
|
||||
}
|
||||
|
||||
$searchIdCache = Redis::get(self::type . 'lastSearchId');
|
||||
$offsetCache = Redis::get(self::type . 'nextOffset');
|
||||
$totalCache = Redis::get(self::type . 'totalCache');
|
||||
if (!isset($searchIdCache) || empty($searchIdCache)) {
|
||||
$searchIdCache = '';
|
||||
}
|
||||
if (!isset($offsetCache) || empty($searchIdCache)) {
|
||||
$offsetCache = 0;
|
||||
}
|
||||
if (!isset($totalCache) || empty($searchIdCache)) {
|
||||
$totalCache = 0;
|
||||
}
|
||||
|
||||
//判断国家是否跑完。
|
||||
if ($totalCache > 0 && $offsetCache > ceil($totalCache / self::limit)) {
|
||||
$key = array_search($countryCache, self::countries, true);
|
||||
if (in_array($countryCache, self::countries) && isset(self::countries[$key + 1])) {
|
||||
$countryCache = self::countries[$key + 1];
|
||||
dump('更新' . $countryCache . '国家的tiktok Ads 完成');
|
||||
} else {
|
||||
$countryCache = 'All'; //赋值非正常国家的code中断定时任务
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$start_time = $dayBeforeYesterdayStart;
|
||||
$end_time = $yesterdayStart;
|
||||
//当前国家爬取
|
||||
$currentParams = null;
|
||||
$currentParams = ['country' => $countryCache, 'search_id' => $searchIdCache, 'type' => 1, 'start_time' => $start_time, 'end_time' => $end_time];
|
||||
|
||||
|
||||
$url = 'https://library.tiktok.com/api/v1/search?region=' . $currentParams['country'] . '&type=' . $currentParams['type'] . '&start_time=' . $currentParams['start_time'] . '&end_time=' . $currentParams['end_time'];
|
||||
|
||||
$res = json_decode($client->post($url, [
|
||||
'headers' => [
|
||||
'accept' => 'application/json, text/plain, */*',
|
||||
'accept-language' => 'zh-CN,zh;q=0.9',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'cookie: _ttp=2ov8Fc4C2CaNscHJd90O9fMhlpE; _ga=GA1.1.1025820618.1731926196; FPID=FPID2.2.Bcgkp%2Fk%2Bbn5w5YeSMR9wd9VpNHJwTUpkkaEqSdCEa0w%3D.1731926196; FPAU=1.2.944915349.1731926193; FPLC=mbVyryI5aG6IVpAvhs1JsgWjA7FVA6QsCJ7VbXhM7zWoXNp4rcD0IK7FNTTf%2FuOrqeOgqEhTd4NB3hY7q3aDVTGQa3WGHqxkGte4%2BBZxsrpaHFas9kb7DPRXM12T5Q%3D%3D; _ga_TEQXTT9FE4=GS1.1.1732097542.7.0.1732097542.0.0.857840528',
|
||||
'origin' => 'https://library.tiktok.com',
|
||||
'priority' => 'u=1, i',
|
||||
'referer' => 'https://library.tiktok.com/ads?region=AT&start_time=1731945600000&end_time=1732032000000&adv_name=&adv_biz_ids=&query_type=&sort_type=last_shown_date,desc',
|
||||
'sec-ch-ua' => '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile' => '?0',
|
||||
'sec-ch-ua-platform' => '"Windows"',
|
||||
'sec-fetch-dest' => 'empty',
|
||||
'sec-fetch-mode' => 'cors',
|
||||
'sec-fetch-site' => 'same-origin',
|
||||
'user-agent' => self::userAgent,
|
||||
// 'user-agent' => 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
],
|
||||
'json' => [
|
||||
'query' => '',
|
||||
'query_type' => '',
|
||||
'adv_biz_ids' => '',
|
||||
'order' => self::sort_order,
|
||||
'offset' => (int)$offsetCache,
|
||||
'search_id' => $currentParams['search_id'],
|
||||
'limit' => self::limit,
|
||||
],
|
||||
|
||||
])->getBody()->getContents(), true);
|
||||
// dump($res);return; //调试点
|
||||
|
||||
if ($res['search_id'] != $searchIdCache) {
|
||||
$searchIdCache = $res['search_id'];
|
||||
dump('search_id更新 ' . $searchIdCache . ' 成功');
|
||||
}
|
||||
|
||||
|
||||
if ($res['total'] == 0 || $res['code'] != 0) {
|
||||
dump('更新tiktok Ads接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
}
|
||||
$listAdsIds = [];
|
||||
foreach ($res['data'] as $ad) {
|
||||
if ($ad['audit_status'] == 2 || empty($ad['videos'])) {
|
||||
continue; //审核不过或者没视频不采集
|
||||
}
|
||||
|
||||
$imagesJson = is_array($ad['image_urls']) ? json_encode($ad['image_urls']) : json_encode([]);
|
||||
$rejection_info = is_array($ad['rejection_info']) ? json_encode($ad['rejection_info']) : null;
|
||||
// dump($rejection_info);
|
||||
$insertData[$ad['id']] = [
|
||||
'ad_id' => $ad['id'],
|
||||
'name' => $ad['name'],
|
||||
'audit_status' => $ad['audit_status'],
|
||||
'type' => $ad['type'],
|
||||
'first_shown_date' => $ad['first_shown_date'],
|
||||
'last_shown_date' => $ad['last_shown_date'],
|
||||
'image_urls' => $imagesJson,
|
||||
'estimated_audience' => $ad['estimated_audience'],
|
||||
'spent' => $ad['spent'],
|
||||
'impression' => $ad['impression'],
|
||||
'show_mode' => $ad['show_mode'],
|
||||
'rejection_info' => $rejection_info,
|
||||
'sor_audit_status' => $ad['sor_audit_status'],
|
||||
'country_code' => $countryCache,
|
||||
];
|
||||
if (isset($ad['videos']) && !empty($ad['videos'])) {
|
||||
// 遍历 "videos" 数组
|
||||
foreach ($ad['videos'] as $video) {
|
||||
$insertData[$ad['id']]['video_url'] = $video['video_url'];
|
||||
$insertData[$ad['id']]['cover_img'] = $video['cover_img'];
|
||||
}
|
||||
}
|
||||
$listAdsIds = array_column($insertData, 'ad_id');
|
||||
|
||||
}
|
||||
// dump($insertData);return;
|
||||
|
||||
|
||||
if (empty($insertData)) return;
|
||||
|
||||
//开启事务
|
||||
Db::beginTransaction();
|
||||
|
||||
|
||||
//删除原来的旧数据
|
||||
TiktokAd::query()->whereIn('ad_id', array_keys($insertData))->delete();
|
||||
//添加新的数据
|
||||
TiktokAd::query()->insert($insertData);
|
||||
|
||||
//redis缓存
|
||||
Redis::set(self::type, json_encode($insertData, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//redis缓存 记录更新时间
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Redis::set(self::type . 'time', $time);
|
||||
Redis::set(self::type . 'lastCountry', $countryCache);
|
||||
Redis::set(self::type . 'nextOffset', ++$offsetCache); //记录下一次的offset
|
||||
Redis::set(self::type . 'totalCache', $res['total']);
|
||||
Redis::set(self::type . 'lastSearchId', $searchIdCache);
|
||||
if (!empty($listAdsIds)) {
|
||||
Redis::rPush(self::type . 'AdsIds', ...$listAdsIds);
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
//销毁$res
|
||||
unset($res);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||
} catch (GuzzleException|\Exception $exception) {
|
||||
//回滚事务
|
||||
Db::rollBack();
|
||||
dump('更' . self::type . '异常:' . $exception->getMessage());
|
||||
dump($exception);
|
||||
}
|
||||
// } catch (ClientExceptionInterface $e) {
|
||||
// // 捕获 4xx 错误
|
||||
// dump( 'Client error: ' . $e->getMessage() . "\n");
|
||||
// } catch (ServerExceptionInterface $e) {
|
||||
// // 捕获 5xx 错误
|
||||
// dump('Server error: ' . $e->getMessage() . "\n");
|
||||
// } catch (TransportExceptionInterface $e) {
|
||||
// // 捕获网络传输错误
|
||||
// dump('Transport error: ' . $e->getMessage() . "\n") ;
|
||||
// } catch (\Exception $e) {
|
||||
// // 捕获所有其他错误
|
||||
// dump('General error: ' . $e->getMessage() . "\n") ;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// 可以加入一些公共方法
|
||||
protected function successResponse($data): Response
|
||||
{
|
||||
|
@ -7,15 +7,11 @@ use app\service\GoogleAdsAssetService;
|
||||
use app\service\GoogleOAuthService;
|
||||
use app\service\GoogleAdsAccountService;
|
||||
use Google\ApiCore\ApiException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use support\Db;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
|
||||
|
||||
//use QL\QueryList;
|
||||
use support\Redis;
|
||||
|
||||
|
||||
class GoogleAdsCustomers
|
||||
@ -35,21 +31,8 @@ class GoogleAdsCustomers
|
||||
|
||||
private $googleAdsAccountService;
|
||||
|
||||
|
||||
//微博热榜地址
|
||||
// const url = 'https://library.tiktok.com/api/v1/search?region=GB&type=1&start_time=1666540800&end_time=1666627200';
|
||||
|
||||
const userAgent = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||||
|
||||
const type = 'googleadscustomers';
|
||||
const CUSTOMERADD = 'googleadsaddcustomers';
|
||||
const limit = 12;
|
||||
const sort_order = 'impression,desc';
|
||||
|
||||
|
||||
// const countries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE","IT", "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "CH", "TR", "GB"] ;
|
||||
const countries = ["GB", "BE"];
|
||||
|
||||
const event = 'googleads:customers:event';
|
||||
const add_queue = 'googleads:customers:add:queue';
|
||||
|
||||
public function addCustomers()
|
||||
{
|
||||
@ -86,20 +69,12 @@ class GoogleAdsCustomers
|
||||
$this->googleOAuthService->saveThirdUserAdvertiser($account['customer_id'], $thirdUser->id, $rootAccountId, $account);
|
||||
}
|
||||
}
|
||||
$this->googleOAuthService->updateThirdUserDefault($thirdUser->id, 't');
|
||||
$this->googleOAuthService->updateThirdUserDefault($thirdUser->id, 't');
|
||||
// return $this->successResponse($allAccounts);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function listCustomers(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getCustomers($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* get assets
|
||||
* @throws ApiException
|
||||
@ -119,204 +94,6 @@ class GoogleAdsCustomers
|
||||
// return $this->successResponse(['ads_list' => $resourceName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天爬取tiktok广告
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
try {
|
||||
|
||||
$client = new Client([
|
||||
//允许重定向
|
||||
// 'allow_redirects' => true,
|
||||
]);
|
||||
|
||||
|
||||
// 获取前两天 0 点的时间戳
|
||||
$dayBeforeYesterdayStart = strtotime('-2 days 00:00:00');
|
||||
|
||||
// 获取前一天 0 点的时间戳
|
||||
$yesterdayStart = strtotime('-1 day 00:00:00');
|
||||
$countryCache = Redis::get(self::type . 'lastCountry');
|
||||
//全部跑完跳出
|
||||
if ($countryCache == 'All') {
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($countryCache)) {
|
||||
$countryCache = 'GB';
|
||||
}
|
||||
|
||||
$searchIdCache = Redis::get(self::type . 'lastSearchId');
|
||||
$offsetCache = Redis::get(self::type . 'nextOffset');
|
||||
$totalCache = Redis::get(self::type . 'totalCache');
|
||||
if (!isset($searchIdCache) || empty($searchIdCache)) {
|
||||
$searchIdCache = '';
|
||||
}
|
||||
if (!isset($offsetCache) || empty($searchIdCache)) {
|
||||
$offsetCache = 0;
|
||||
}
|
||||
if (!isset($totalCache) || empty($searchIdCache)) {
|
||||
$totalCache = 0;
|
||||
}
|
||||
|
||||
//判断国家是否跑完。
|
||||
if ($totalCache > 0 && $offsetCache > ceil($totalCache / self::limit)) {
|
||||
$key = array_search($countryCache, self::countries, true);
|
||||
if (in_array($countryCache, self::countries) && isset(self::countries[$key + 1])) {
|
||||
$countryCache = self::countries[$key + 1];
|
||||
dump('更新' . $countryCache . '国家的tiktok Ads 完成');
|
||||
} else {
|
||||
$countryCache = 'All'; //赋值非正常国家的code中断定时任务
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$start_time = $dayBeforeYesterdayStart;
|
||||
$end_time = $yesterdayStart;
|
||||
//当前国家爬取
|
||||
$currentParams = null;
|
||||
$currentParams = ['country' => $countryCache, 'search_id' => $searchIdCache, 'type' => 1, 'start_time' => $start_time, 'end_time' => $end_time];
|
||||
|
||||
|
||||
$url = 'https://library.tiktok.com/api/v1/search?region=' . $currentParams['country'] . '&type=' . $currentParams['type'] . '&start_time=' . $currentParams['start_time'] . '&end_time=' . $currentParams['end_time'];
|
||||
|
||||
$res = json_decode($client->post($url, [
|
||||
'headers' => [
|
||||
'accept' => 'application/json, text/plain, */*',
|
||||
'accept-language' => 'zh-CN,zh;q=0.9',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'cookie: _ttp=2ov8Fc4C2CaNscHJd90O9fMhlpE; _ga=GA1.1.1025820618.1731926196; FPID=FPID2.2.Bcgkp%2Fk%2Bbn5w5YeSMR9wd9VpNHJwTUpkkaEqSdCEa0w%3D.1731926196; FPAU=1.2.944915349.1731926193; FPLC=mbVyryI5aG6IVpAvhs1JsgWjA7FVA6QsCJ7VbXhM7zWoXNp4rcD0IK7FNTTf%2FuOrqeOgqEhTd4NB3hY7q3aDVTGQa3WGHqxkGte4%2BBZxsrpaHFas9kb7DPRXM12T5Q%3D%3D; _ga_TEQXTT9FE4=GS1.1.1732097542.7.0.1732097542.0.0.857840528',
|
||||
'origin' => 'https://library.tiktok.com',
|
||||
'priority' => 'u=1, i',
|
||||
'referer' => 'https://library.tiktok.com/ads?region=AT&start_time=1731945600000&end_time=1732032000000&adv_name=&adv_biz_ids=&query_type=&sort_type=last_shown_date,desc',
|
||||
'sec-ch-ua' => '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile' => '?0',
|
||||
'sec-ch-ua-platform' => '"Windows"',
|
||||
'sec-fetch-dest' => 'empty',
|
||||
'sec-fetch-mode' => 'cors',
|
||||
'sec-fetch-site' => 'same-origin',
|
||||
'user-agent' => self::userAgent,
|
||||
// 'user-agent' => 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
],
|
||||
'json' => [
|
||||
'query' => '',
|
||||
'query_type' => '',
|
||||
'adv_biz_ids' => '',
|
||||
'order' => self::sort_order,
|
||||
'offset' => (int)$offsetCache,
|
||||
'search_id' => $currentParams['search_id'],
|
||||
'limit' => self::limit,
|
||||
],
|
||||
|
||||
])->getBody()->getContents(), true);
|
||||
// dump($res);return; //调试点
|
||||
|
||||
if ($res['search_id'] != $searchIdCache) {
|
||||
$searchIdCache = $res['search_id'];
|
||||
dump('search_id更新 ' . $searchIdCache . ' 成功');
|
||||
}
|
||||
|
||||
|
||||
if ($res['total'] == 0 || $res['code'] != 0) {
|
||||
dump('更新tiktok Ads接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
}
|
||||
$listAdsIds = [];
|
||||
foreach ($res['data'] as $ad) {
|
||||
if ($ad['audit_status'] == 2 || empty($ad['videos'])) {
|
||||
continue; //审核不过或者没视频不采集
|
||||
}
|
||||
|
||||
$imagesJson = is_array($ad['image_urls']) ? json_encode($ad['image_urls']) : json_encode([]);
|
||||
$rejection_info = is_array($ad['rejection_info']) ? json_encode($ad['rejection_info']) : null;
|
||||
// dump($rejection_info);
|
||||
$insertData[$ad['id']] = [
|
||||
'ad_id' => $ad['id'],
|
||||
'name' => $ad['name'],
|
||||
'audit_status' => $ad['audit_status'],
|
||||
'type' => $ad['type'],
|
||||
'first_shown_date' => $ad['first_shown_date'],
|
||||
'last_shown_date' => $ad['last_shown_date'],
|
||||
'image_urls' => $imagesJson,
|
||||
'estimated_audience' => $ad['estimated_audience'],
|
||||
'spent' => $ad['spent'],
|
||||
'impression' => $ad['impression'],
|
||||
'show_mode' => $ad['show_mode'],
|
||||
'rejection_info' => $rejection_info,
|
||||
'sor_audit_status' => $ad['sor_audit_status'],
|
||||
'country_code' => $countryCache,
|
||||
];
|
||||
if (isset($ad['videos']) && !empty($ad['videos'])) {
|
||||
// 遍历 "videos" 数组
|
||||
foreach ($ad['videos'] as $video) {
|
||||
$insertData[$ad['id']]['video_url'] = $video['video_url'];
|
||||
$insertData[$ad['id']]['cover_img'] = $video['cover_img'];
|
||||
}
|
||||
}
|
||||
$listAdsIds = array_column($insertData, 'ad_id');
|
||||
|
||||
}
|
||||
// dump($insertData);return;
|
||||
|
||||
|
||||
if (empty($insertData)) return;
|
||||
|
||||
//开启事务
|
||||
Db::beginTransaction();
|
||||
|
||||
|
||||
//删除原来的旧数据
|
||||
TiktokAd::query()->whereIn('ad_id', array_keys($insertData))->delete();
|
||||
//添加新的数据
|
||||
TiktokAd::query()->insert($insertData);
|
||||
|
||||
//redis缓存
|
||||
Redis::set(self::type, json_encode($insertData, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//redis缓存 记录更新时间
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Redis::set(self::type . 'time', $time);
|
||||
Redis::set(self::type . 'lastCountry', $countryCache);
|
||||
Redis::set(self::type . 'nextOffset', ++$offsetCache); //记录下一次的offset
|
||||
Redis::set(self::type . 'totalCache', $res['total']);
|
||||
Redis::set(self::type . 'lastSearchId', $searchIdCache);
|
||||
if (!empty($listAdsIds)) {
|
||||
Redis::rPush(self::type . 'AdsIds', ...$listAdsIds);
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
//销毁$res
|
||||
unset($res);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||
} catch (GuzzleException|\Exception $exception) {
|
||||
//回滚事务
|
||||
Db::rollBack();
|
||||
dump('更' . self::type . '异常:' . $exception->getMessage());
|
||||
dump($exception);
|
||||
}
|
||||
// } catch (ClientExceptionInterface $e) {
|
||||
// // 捕获 4xx 错误
|
||||
// dump( 'Client error: ' . $e->getMessage() . "\n");
|
||||
// } catch (ServerExceptionInterface $e) {
|
||||
// // 捕获 5xx 错误
|
||||
// dump('Server error: ' . $e->getMessage() . "\n");
|
||||
// } catch (TransportExceptionInterface $e) {
|
||||
// // 捕获网络传输错误
|
||||
// dump('Transport error: ' . $e->getMessage() . "\n") ;
|
||||
// } catch (\Exception $e) {
|
||||
// // 捕获所有其他错误
|
||||
// dump('General error: ' . $e->getMessage() . "\n") ;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// 可以加入一些公共方法
|
||||
protected function successResponse($data): Response
|
||||
{
|
||||
|
@ -2,19 +2,16 @@
|
||||
|
||||
namespace app\event;
|
||||
|
||||
use app\model\Campaign;
|
||||
use app\service\GoogleAdsCampaignService;
|
||||
use app\service\GoogleOAuthService;
|
||||
use Google\ApiCore\ApiException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use support\Db;
|
||||
use support\Request;
|
||||
|
||||
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
use Webman\RedisQueue\Redis;
|
||||
|
||||
//use QL\QueryList;
|
||||
use support\Redis;
|
||||
|
||||
|
||||
class GoogleAdsDateDatas
|
||||
@ -27,247 +24,40 @@ class GoogleAdsDateDatas
|
||||
|
||||
private $googleOAuthService;
|
||||
|
||||
const event = 'googleads:datedatas:event';
|
||||
const queue = 'googleads:datedatas:queue';
|
||||
|
||||
//微博热榜地址
|
||||
// const url = 'https://library.tiktok.com/api/v1/search?region=GB&type=1&start_time=1666540800&end_time=1666627200';
|
||||
|
||||
// const userAgent = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||||
|
||||
const type = 'googleadsgdatedatas';
|
||||
const limit = 12;
|
||||
const sort_order = 'impression,desc';
|
||||
|
||||
|
||||
// const countries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE","IT", "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "CH", "TR", "GB"] ;
|
||||
const countries = ["GB", "BE"];
|
||||
|
||||
|
||||
public function listCampaigns(Request $request)
|
||||
public function syncDateDatas($options)
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getCampaigns($options);
|
||||
$queue = self::queue;
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
if ($customer['login_customer_id'] > 0) {
|
||||
$customer['date'] = $options['date'];
|
||||
Redis::send($queue, $customer);
|
||||
}
|
||||
}
|
||||
return 'redis queue ok';
|
||||
}
|
||||
|
||||
/**
|
||||
* get date datas
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getDateDatas($options)
|
||||
public function getDateDatas($customer)
|
||||
{
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
// dump($customers);
|
||||
foreach ($customers as $customer) {
|
||||
if ($customer['login_customer_id'] > 0 && ((isset($customer['manager']) && $customer['manager'] === false)) ) {
|
||||
|
||||
if ($customer['login_customer_id'] > 0 && ((isset($customer['manager']) && $customer['manager'] === false))) {
|
||||
// dump($customer);
|
||||
$googleAdsCampaignService = new googleAdsCampaignService($customer['customer_id']);
|
||||
$googleAdsCampaignService = new googleAdsCampaignService($customer['customer_id']);
|
||||
// dump($customer['customer_id'],$customer, $options['date']);
|
||||
$googleAdsCampaignService->runListDateDatas($customer['customer_id'],$customer, $options['date']);
|
||||
}
|
||||
$googleAdsCampaignService->runListDateDatas($customer['customer_id'], $customer, $customer['date']);
|
||||
}
|
||||
|
||||
// $this->googleAdsCampaignService->runListDateDatas($options['customer_id'], $options['date']);
|
||||
// return $this->successResponse(['data' => $resourceName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 每天爬取tiktok广告
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
try {
|
||||
|
||||
$client = new Client([
|
||||
//允许重定向
|
||||
// 'allow_redirects' => true,
|
||||
]);
|
||||
|
||||
|
||||
// 获取前两天 0 点的时间戳
|
||||
$dayBeforeYesterdayStart = strtotime('-2 days 00:00:00');
|
||||
|
||||
// 获取前一天 0 点的时间戳
|
||||
$yesterdayStart = strtotime('-1 day 00:00:00');
|
||||
$countryCache = Redis::get(self::type . 'lastCountry');
|
||||
//全部跑完跳出
|
||||
if ($countryCache == 'All') {
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($countryCache)) {
|
||||
$countryCache = 'GB';
|
||||
}
|
||||
|
||||
$searchIdCache = Redis::get(self::type . 'lastSearchId');
|
||||
$offsetCache = Redis::get(self::type . 'nextOffset');
|
||||
$totalCache = Redis::get(self::type . 'totalCache');
|
||||
if (!isset($searchIdCache) || empty($searchIdCache)) {
|
||||
$searchIdCache = '';
|
||||
}
|
||||
if (!isset($offsetCache) || empty($searchIdCache)) {
|
||||
$offsetCache = 0;
|
||||
}
|
||||
if (!isset($totalCache) || empty($searchIdCache)) {
|
||||
$totalCache = 0;
|
||||
}
|
||||
|
||||
//判断国家是否跑完。
|
||||
if ($totalCache > 0 && $offsetCache > ceil($totalCache / self::limit)) {
|
||||
$key = array_search($countryCache, self::countries, true);
|
||||
if (in_array($countryCache, self::countries) && isset(self::countries[$key + 1])) {
|
||||
$countryCache = self::countries[$key + 1];
|
||||
dump('更新' . $countryCache . '国家的tiktok Ads 完成');
|
||||
} else {
|
||||
$countryCache = 'All'; //赋值非正常国家的code中断定时任务
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$start_time = $dayBeforeYesterdayStart;
|
||||
$end_time = $yesterdayStart;
|
||||
//当前国家爬取
|
||||
$currentParams = null;
|
||||
$currentParams = ['country' => $countryCache, 'search_id' => $searchIdCache, 'type' => 1, 'start_time' => $start_time, 'end_time' => $end_time];
|
||||
|
||||
|
||||
$url = 'https://library.tiktok.com/api/v1/search?region=' . $currentParams['country'] . '&type=' . $currentParams['type'] . '&start_time=' . $currentParams['start_time'] . '&end_time=' . $currentParams['end_time'];
|
||||
|
||||
$res = json_decode($client->post($url, [
|
||||
'headers' => [
|
||||
'accept' => 'application/json, text/plain, */*',
|
||||
'accept-language' => 'zh-CN,zh;q=0.9',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'cookie: _ttp=2ov8Fc4C2CaNscHJd90O9fMhlpE; _ga=GA1.1.1025820618.1731926196; FPID=FPID2.2.Bcgkp%2Fk%2Bbn5w5YeSMR9wd9VpNHJwTUpkkaEqSdCEa0w%3D.1731926196; FPAU=1.2.944915349.1731926193; FPLC=mbVyryI5aG6IVpAvhs1JsgWjA7FVA6QsCJ7VbXhM7zWoXNp4rcD0IK7FNTTf%2FuOrqeOgqEhTd4NB3hY7q3aDVTGQa3WGHqxkGte4%2BBZxsrpaHFas9kb7DPRXM12T5Q%3D%3D; _ga_TEQXTT9FE4=GS1.1.1732097542.7.0.1732097542.0.0.857840528',
|
||||
'origin' => 'https://library.tiktok.com',
|
||||
'priority' => 'u=1, i',
|
||||
'referer' => 'https://library.tiktok.com/ads?region=AT&start_time=1731945600000&end_time=1732032000000&adv_name=&adv_biz_ids=&query_type=&sort_type=last_shown_date,desc',
|
||||
'sec-ch-ua' => '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile' => '?0',
|
||||
'sec-ch-ua-platform' => '"Windows"',
|
||||
'sec-fetch-dest' => 'empty',
|
||||
'sec-fetch-mode' => 'cors',
|
||||
'sec-fetch-site' => 'same-origin',
|
||||
'user-agent' => self::userAgent,
|
||||
// 'user-agent' => 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
],
|
||||
'json' => [
|
||||
'query' => '',
|
||||
'query_type' => '',
|
||||
'adv_biz_ids' => '',
|
||||
'order' => self::sort_order,
|
||||
'offset' => (int)$offsetCache,
|
||||
'search_id' => $currentParams['search_id'],
|
||||
'limit' => self::limit,
|
||||
],
|
||||
|
||||
])->getBody()->getContents(), true);
|
||||
// dump($res);return; //调试点
|
||||
|
||||
if ($res['search_id'] != $searchIdCache) {
|
||||
$searchIdCache = $res['search_id'];
|
||||
dump('search_id更新 ' . $searchIdCache . ' 成功');
|
||||
}
|
||||
|
||||
|
||||
if ($res['total'] == 0 || $res['code'] != 0) {
|
||||
dump('更新tiktok Ads接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
}
|
||||
$listAdsIds = [];
|
||||
foreach ($res['data'] as $ad) {
|
||||
if ($ad['audit_status'] == 2 || empty($ad['videos'])) {
|
||||
continue; //审核不过或者没视频不采集
|
||||
}
|
||||
|
||||
$imagesJson = is_array($ad['image_urls']) ? json_encode($ad['image_urls']) : json_encode([]);
|
||||
$rejection_info = is_array($ad['rejection_info']) ? json_encode($ad['rejection_info']) : null;
|
||||
// dump($rejection_info);
|
||||
$insertData[$ad['id']] = [
|
||||
'ad_id' => $ad['id'],
|
||||
'name' => $ad['name'],
|
||||
'audit_status' => $ad['audit_status'],
|
||||
'type' => $ad['type'],
|
||||
'first_shown_date' => $ad['first_shown_date'],
|
||||
'last_shown_date' => $ad['last_shown_date'],
|
||||
'image_urls' => $imagesJson,
|
||||
'estimated_audience' => $ad['estimated_audience'],
|
||||
'spent' => $ad['spent'],
|
||||
'impression' => $ad['impression'],
|
||||
'show_mode' => $ad['show_mode'],
|
||||
'rejection_info' => $rejection_info,
|
||||
'sor_audit_status' => $ad['sor_audit_status'],
|
||||
'country_code' => $countryCache,
|
||||
];
|
||||
if (isset($ad['videos']) && !empty($ad['videos'])) {
|
||||
// 遍历 "videos" 数组
|
||||
foreach ($ad['videos'] as $video) {
|
||||
$insertData[$ad['id']]['video_url'] = $video['video_url'];
|
||||
$insertData[$ad['id']]['cover_img'] = $video['cover_img'];
|
||||
}
|
||||
}
|
||||
$listAdsIds = array_column($insertData, 'ad_id');
|
||||
|
||||
}
|
||||
// dump($insertData);return;
|
||||
|
||||
|
||||
if (empty($insertData)) return;
|
||||
|
||||
//开启事务
|
||||
Db::beginTransaction();
|
||||
|
||||
|
||||
//删除原来的旧数据
|
||||
TiktokAd::query()->whereIn('ad_id', array_keys($insertData))->delete();
|
||||
//添加新的数据
|
||||
TiktokAd::query()->insert($insertData);
|
||||
|
||||
//redis缓存
|
||||
Redis::set(self::type, json_encode($insertData, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//redis缓存 记录更新时间
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Redis::set(self::type . 'time', $time);
|
||||
Redis::set(self::type . 'lastCountry', $countryCache);
|
||||
Redis::set(self::type . 'nextOffset', ++$offsetCache); //记录下一次的offset
|
||||
Redis::set(self::type . 'totalCache', $res['total']);
|
||||
Redis::set(self::type . 'lastSearchId', $searchIdCache);
|
||||
if (!empty($listAdsIds)) {
|
||||
Redis::rPush(self::type . 'AdsIds', ...$listAdsIds);
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
//销毁$res
|
||||
unset($res);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||
} catch (GuzzleException|\Exception $exception) {
|
||||
//回滚事务
|
||||
Db::rollBack();
|
||||
dump('更' . self::type . '异常:' . $exception->getMessage());
|
||||
dump($exception);
|
||||
}
|
||||
// } catch (ClientExceptionInterface $e) {
|
||||
// // 捕获 4xx 错误
|
||||
// dump( 'Client error: ' . $e->getMessage() . "\n");
|
||||
// } catch (ServerExceptionInterface $e) {
|
||||
// // 捕获 5xx 错误
|
||||
// dump('Server error: ' . $e->getMessage() . "\n");
|
||||
// } catch (TransportExceptionInterface $e) {
|
||||
// // 捕获网络传输错误
|
||||
// dump('Transport error: ' . $e->getMessage() . "\n") ;
|
||||
// } catch (\Exception $e) {
|
||||
// // 捕获所有其他错误
|
||||
// dump('General error: ' . $e->getMessage() . "\n") ;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// 可以加入一些公共方法
|
||||
protected function successResponse($data): Response
|
||||
|
@ -2,20 +2,16 @@
|
||||
|
||||
namespace app\event;
|
||||
|
||||
use app\model\AdGroup;
|
||||
use app\service\GoogleAdsCampaignService;
|
||||
|
||||
use app\service\GoogleAdsGroupService;
|
||||
use app\service\GoogleOAuthService;
|
||||
use Google\ApiCore\ApiException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use support\Db;
|
||||
use support\Request;
|
||||
|
||||
use support\Response;
|
||||
use DI\Annotation\Inject;
|
||||
|
||||
use Webman\RedisQueue\Redis;
|
||||
//use QL\QueryList;
|
||||
use support\Redis;
|
||||
|
||||
|
||||
|
||||
class GoogleAdsGroups
|
||||
@ -28,243 +24,35 @@ class GoogleAdsGroups
|
||||
private $googleOAuthService;
|
||||
|
||||
|
||||
//微博热榜地址
|
||||
// const url = 'https://library.tiktok.com/api/v1/search?region=GB&type=1&start_time=1666540800&end_time=1666627200';
|
||||
|
||||
const userAgent = 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||||
|
||||
const type = 'googleadsgroups';
|
||||
const limit = 12;
|
||||
const sort_order = 'impression,desc';
|
||||
const event = 'googleads:groups:event';
|
||||
const queue = 'googleads:groups:queue';
|
||||
|
||||
|
||||
// const countries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE","IT", "LV", "LI", "LT", "LU", "MT", "NL", "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "CH", "TR", "GB"] ;
|
||||
const countries = ["GB", "BE"];
|
||||
|
||||
|
||||
public function listGroups(Request $request)
|
||||
public function syncGroups()
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 继续处理 Google Ads API 操作
|
||||
return $this->getGroups($options);
|
||||
$queue = self::queue;
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
foreach ($customers as $customer) {
|
||||
if ($customer['login_customer_id'] >0){
|
||||
Redis::send($queue,$customer);
|
||||
}
|
||||
}
|
||||
return 'redis queue ok';
|
||||
}
|
||||
|
||||
/**
|
||||
* get groups
|
||||
* @throws ApiException
|
||||
*/
|
||||
public function getGroups($options)
|
||||
public function getGroups($customer)
|
||||
{
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers([]);
|
||||
|
||||
foreach ($customers as $customer) {
|
||||
$googleAdsGroupService = new GoogleAdsGroupService($customer['customer_id']);
|
||||
if ($customer['login_customer_id'] >0){
|
||||
$resourceName = $googleAdsGroupService->runListGroups($customer['customer_id'],$customer);
|
||||
}
|
||||
|
||||
// return $this->successResponse(['groups_list' => $resourceName]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 每天爬取tiktok广告
|
||||
* @return void
|
||||
*/
|
||||
public
|
||||
function update()
|
||||
{
|
||||
try {
|
||||
|
||||
$client = new Client([
|
||||
//允许重定向
|
||||
// 'allow_redirects' => true,
|
||||
]);
|
||||
|
||||
|
||||
// 获取前两天 0 点的时间戳
|
||||
$dayBeforeYesterdayStart = strtotime('-2 days 00:00:00');
|
||||
|
||||
// 获取前一天 0 点的时间戳
|
||||
$yesterdayStart = strtotime('-1 day 00:00:00');
|
||||
$countryCache = Redis::get(self::type . 'lastCountry');
|
||||
//全部跑完跳出
|
||||
if ($countryCache == 'All') {
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($countryCache)) {
|
||||
$countryCache = 'GB';
|
||||
}
|
||||
|
||||
$searchIdCache = Redis::get(self::type . 'lastSearchId');
|
||||
$offsetCache = Redis::get(self::type . 'nextOffset');
|
||||
$totalCache = Redis::get(self::type . 'totalCache');
|
||||
if (!isset($searchIdCache) || empty($searchIdCache)) {
|
||||
$searchIdCache = '';
|
||||
}
|
||||
if (!isset($offsetCache) || empty($searchIdCache)) {
|
||||
$offsetCache = 0;
|
||||
}
|
||||
if (!isset($totalCache) || empty($searchIdCache)) {
|
||||
$totalCache = 0;
|
||||
}
|
||||
|
||||
//判断国家是否跑完。
|
||||
if ($totalCache > 0 && $offsetCache > ceil($totalCache / self::limit)) {
|
||||
$key = array_search($countryCache, self::countries, true);
|
||||
if (in_array($countryCache, self::countries) && isset(self::countries[$key + 1])) {
|
||||
$countryCache = self::countries[$key + 1];
|
||||
dump('更新' . $countryCache . '国家的tiktok Ads 完成');
|
||||
} else {
|
||||
$countryCache = 'All'; //赋值非正常国家的code中断定时任务
|
||||
dump($countryCache . '国家更新tiktok Ads 完成');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$start_time = $dayBeforeYesterdayStart;
|
||||
$end_time = $yesterdayStart;
|
||||
//当前国家爬取
|
||||
$currentParams = null;
|
||||
$currentParams = ['country' => $countryCache, 'search_id' => $searchIdCache, 'type' => 1, 'start_time' => $start_time, 'end_time' => $end_time];
|
||||
|
||||
|
||||
$url = 'https://library.tiktok.com/api/v1/search?region=' . $currentParams['country'] . '&type=' . $currentParams['type'] . '&start_time=' . $currentParams['start_time'] . '&end_time=' . $currentParams['end_time'];
|
||||
|
||||
$res = json_decode($client->post($url, [
|
||||
'headers' => [
|
||||
'accept' => 'application/json, text/plain, */*',
|
||||
'accept-language' => 'zh-CN,zh;q=0.9',
|
||||
'content-type' => 'application/json',
|
||||
'cookie' => 'cookie: _ttp=2ov8Fc4C2CaNscHJd90O9fMhlpE; _ga=GA1.1.1025820618.1731926196; FPID=FPID2.2.Bcgkp%2Fk%2Bbn5w5YeSMR9wd9VpNHJwTUpkkaEqSdCEa0w%3D.1731926196; FPAU=1.2.944915349.1731926193; FPLC=mbVyryI5aG6IVpAvhs1JsgWjA7FVA6QsCJ7VbXhM7zWoXNp4rcD0IK7FNTTf%2FuOrqeOgqEhTd4NB3hY7q3aDVTGQa3WGHqxkGte4%2BBZxsrpaHFas9kb7DPRXM12T5Q%3D%3D; _ga_TEQXTT9FE4=GS1.1.1732097542.7.0.1732097542.0.0.857840528',
|
||||
'origin' => 'https://library.tiktok.com',
|
||||
'priority' => 'u=1, i',
|
||||
'referer' => 'https://library.tiktok.com/ads?region=AT&start_time=1731945600000&end_time=1732032000000&adv_name=&adv_biz_ids=&query_type=&sort_type=last_shown_date,desc',
|
||||
'sec-ch-ua' => '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
||||
'sec-ch-ua-mobile' => '?0',
|
||||
'sec-ch-ua-platform' => '"Windows"',
|
||||
'sec-fetch-dest' => 'empty',
|
||||
'sec-fetch-mode' => 'cors',
|
||||
'sec-fetch-site' => 'same-origin',
|
||||
'user-agent' => self::userAgent,
|
||||
// 'user-agent' => 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
|
||||
],
|
||||
'json' => [
|
||||
'query' => '',
|
||||
'query_type' => '',
|
||||
'adv_biz_ids' => '',
|
||||
'order' => self::sort_order,
|
||||
'offset' => (int)$offsetCache,
|
||||
'search_id' => $currentParams['search_id'],
|
||||
'limit' => self::limit,
|
||||
],
|
||||
|
||||
])->getBody()->getContents(), true);
|
||||
// dump($res);return; //调试点
|
||||
|
||||
if ($res['search_id'] != $searchIdCache) {
|
||||
$searchIdCache = $res['search_id'];
|
||||
dump('search_id更新 ' . $searchIdCache . ' 成功');
|
||||
}
|
||||
|
||||
|
||||
if ($res['total'] == 0 || $res['code'] != 0) {
|
||||
dump('更新tiktok Ads接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||
return;
|
||||
}
|
||||
$listAdsIds = [];
|
||||
foreach ($res['data'] as $ad) {
|
||||
if ($ad['audit_status'] == 2 || empty($ad['videos'])) {
|
||||
continue; //审核不过或者没视频不采集
|
||||
}
|
||||
|
||||
$imagesJson = is_array($ad['image_urls']) ? json_encode($ad['image_urls']) : json_encode([]);
|
||||
$rejection_info = is_array($ad['rejection_info']) ? json_encode($ad['rejection_info']) : null;
|
||||
// dump($rejection_info);
|
||||
$insertData[$ad['id']] = [
|
||||
'ad_id' => $ad['id'],
|
||||
'name' => $ad['name'],
|
||||
'audit_status' => $ad['audit_status'],
|
||||
'type' => $ad['type'],
|
||||
'first_shown_date' => $ad['first_shown_date'],
|
||||
'last_shown_date' => $ad['last_shown_date'],
|
||||
'image_urls' => $imagesJson,
|
||||
'estimated_audience' => $ad['estimated_audience'],
|
||||
'spent' => $ad['spent'],
|
||||
'impression' => $ad['impression'],
|
||||
'show_mode' => $ad['show_mode'],
|
||||
'rejection_info' => $rejection_info,
|
||||
'sor_audit_status' => $ad['sor_audit_status'],
|
||||
'country_code' => $countryCache,
|
||||
];
|
||||
if (isset($ad['videos']) && !empty($ad['videos'])) {
|
||||
// 遍历 "videos" 数组
|
||||
foreach ($ad['videos'] as $video) {
|
||||
$insertData[$ad['id']]['video_url'] = $video['video_url'];
|
||||
$insertData[$ad['id']]['cover_img'] = $video['cover_img'];
|
||||
}
|
||||
}
|
||||
$listAdsIds = array_column($insertData, 'ad_id');
|
||||
|
||||
}
|
||||
// dump($insertData);return;
|
||||
|
||||
|
||||
if (empty($insertData)) return;
|
||||
|
||||
//开启事务
|
||||
Db::beginTransaction();
|
||||
|
||||
|
||||
//删除原来的旧数据
|
||||
TiktokAd::query()->whereIn('ad_id', array_keys($insertData))->delete();
|
||||
//添加新的数据
|
||||
TiktokAd::query()->insert($insertData);
|
||||
|
||||
//redis缓存
|
||||
Redis::set(self::type, json_encode($insertData, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
//redis缓存 记录更新时间
|
||||
$time = date('Y-m-d H:i:s');
|
||||
Redis::set(self::type . 'time', $time);
|
||||
Redis::set(self::type . 'lastCountry', $countryCache);
|
||||
Redis::set(self::type . 'nextOffset', ++$offsetCache); //记录下一次的offset
|
||||
Redis::set(self::type . 'totalCache', $res['total']);
|
||||
Redis::set(self::type . 'lastSearchId', $searchIdCache);
|
||||
if (!empty($listAdsIds)) {
|
||||
Redis::rPush(self::type . 'AdsIds', ...$listAdsIds);
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
//销毁$res
|
||||
unset($res);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||
} catch (GuzzleException|\Exception $exception) {
|
||||
//回滚事务
|
||||
Db::rollBack();
|
||||
dump('更' . self::type . '异常:' . $exception->getMessage());
|
||||
dump($exception);
|
||||
}
|
||||
// } catch (ClientExceptionInterface $e) {
|
||||
// // 捕获 4xx 错误
|
||||
// dump( 'Client error: ' . $e->getMessage() . "\n");
|
||||
// } catch (ServerExceptionInterface $e) {
|
||||
// // 捕获 5xx 错误
|
||||
// dump('Server error: ' . $e->getMessage() . "\n");
|
||||
// } catch (TransportExceptionInterface $e) {
|
||||
// // 捕获网络传输错误
|
||||
// dump('Transport error: ' . $e->getMessage() . "\n") ;
|
||||
// } catch (\Exception $e) {
|
||||
// // 捕获所有其他错误
|
||||
// dump('General error: ' . $e->getMessage() . "\n") ;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// 可以加入一些公共方法
|
||||
protected
|
||||
|
@ -24,77 +24,67 @@ class UpdateGoogleAdsTask
|
||||
|
||||
|
||||
// 每15分钟执行一次
|
||||
new Crontab('10 */3 * * * *', function () {
|
||||
new Crontab('10 */13 * * * *', function () {
|
||||
|
||||
$dayBeforeYesterdayStart = date('Y-m-d', strtotime('-2 day'));
|
||||
dump($dayBeforeYesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::type, ['date' => $dayBeforeYesterdayStart]);
|
||||
dump($dayBeforeYesterdayStart . '更新' . GoogleAdsDateDatas::event . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::event, ['date' => $dayBeforeYesterdayStart]);
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// 每15分钟执行一次
|
||||
new Crontab('20 */3 * * * *', function () {
|
||||
new Crontab('20 */13 * * * *', function () {
|
||||
$yesterdayStart = date('Y-m-d', strtotime('-1 day'));
|
||||
dump($yesterdayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::type, ['date' => $yesterdayStart]);
|
||||
dump($yesterdayStart . '更新' . GoogleAdsDateDatas::event . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::event, ['date' => $yesterdayStart]);
|
||||
}
|
||||
);
|
||||
|
||||
// 每15分钟执行一次
|
||||
new Crontab('30 */3 * * * *', function () {
|
||||
new Crontab('30 */12 * * * *', function () {
|
||||
//获取今天的 0 点的YYYY - MM - DD格式
|
||||
$todayStart = date('Y-m-d', strtotime('0 day'));
|
||||
dump($todayStart . '更新' . GoogleAdsDateDatas::type . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::type, ['date' => $todayStart]);
|
||||
dump($todayStart . '更新' . GoogleAdsDateDatas::event . '开始');
|
||||
Event::emit(GoogleAdsDateDatas::event, ['date' => $todayStart]);
|
||||
}
|
||||
);
|
||||
// 每15分钟执行一次
|
||||
new Crontab('15 */3 * * * *', function () {
|
||||
new Crontab('15 */12 * * * *', function () {
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssetRelations::IMAGEASSET . '开始');
|
||||
Event::emit(GoogleAdsAssetRelations::IMAGEASSET, []);
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssetRelations::event . '开始');
|
||||
Event::emit(GoogleAdsAssetRelations::event, []);
|
||||
}
|
||||
);
|
||||
|
||||
// 每15分钟执行一次
|
||||
new Crontab('30 */3 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsGroups::type . '开始');
|
||||
Event::emit(GoogleAdsGroups::type, []);
|
||||
new Crontab('30 */12 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsGroups::event . '开始');
|
||||
Event::emit(GoogleAdsGroups::event, []);
|
||||
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCampaigns::type . '开始');
|
||||
Event::emit(GoogleAdsCampaigns::type, []);
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCampaigns::event . '开始');
|
||||
Event::emit(GoogleAdsCampaigns::event, []);
|
||||
}
|
||||
);
|
||||
|
||||
// 每15分钟执行一次
|
||||
new Crontab('5 */11 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAds::type . '开始');
|
||||
Event::emit(GoogleAdsAds::type, []);
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAds::event . '开始');
|
||||
Event::emit(GoogleAdsAds::event, []);
|
||||
}
|
||||
|
||||
);
|
||||
// 每15分钟执行一次
|
||||
new Crontab('25 */19 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssets::type . '开始');
|
||||
Event::emit(GoogleAdsAssets::type, []);
|
||||
new Crontab('25 */10 * * * *', function () {
|
||||
|
||||
// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssets::event . '开始');
|
||||
// Event::emit(GoogleAdsAssets::event, []);
|
||||
}
|
||||
);
|
||||
|
||||
// new Crontab('* */2 * * * *', function () {
|
||||
// dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssetRelations::IMAGEASSET . '开始');
|
||||
// Event::emit(GoogleAdsAssetRelations::IMAGEASSET, []);
|
||||
// });
|
||||
|
||||
new Crontab('55 */51 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsAssetRelations::VIDEOASSET . '开始');
|
||||
Event::emit(GoogleAdsAssetRelations::VIDEOASSET, []);
|
||||
}
|
||||
);
|
||||
|
||||
new Crontab('0 */1 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCustomers::CUSTOMERADD . '开始');
|
||||
Event::emit(GoogleAdsCustomers::CUSTOMERADD, []);
|
||||
new Crontab('16 */14 * * * *', function () {
|
||||
dump(date('Y-m-d H:i:s') . '更新' . GoogleAdsCustomers::event . '开始');
|
||||
Event::emit(GoogleAdsCustomers::event, []);
|
||||
}
|
||||
);
|
||||
|
||||
|
24
app/queue/redis/GoogleAdsAdQueue.php
Normal file
24
app/queue/redis/GoogleAdsAdQueue.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use app\event\GoogleAdsAds;
|
||||
use Webman\Event\Event;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class GoogleAdsAdQueue implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = GoogleAdsAds::queue;
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
// dump($this->queue.' consumed',$data);
|
||||
Event::emit(GoogleAdsAds::queue, $data);
|
||||
}
|
||||
|
||||
}
|
24
app/queue/redis/GoogleAdsAssetQueue.php
Normal file
24
app/queue/redis/GoogleAdsAssetQueue.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use app\event\GoogleAdsAssets;
|
||||
use Webman\Event\Event;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class GoogleAdsAssetQueue implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = GoogleAdsAssets::queue;
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
// dump($this->queue.' consumed',$data);
|
||||
Event::emit(GoogleAdsAssets::queue, $data);
|
||||
}
|
||||
|
||||
}
|
24
app/queue/redis/GoogleAdsAssetRelationQueue.php
Normal file
24
app/queue/redis/GoogleAdsAssetRelationQueue.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use app\event\GoogleAdsAssetRelations;
|
||||
use Webman\Event\Event;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class GoogleAdsAssetRelationQueue implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = GoogleAdsAssetRelations::queue;
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
// dump($this->queue.' consumed',$data);
|
||||
Event::emit(GoogleAdsAssetRelations::queue, $data);
|
||||
}
|
||||
|
||||
}
|
24
app/queue/redis/GoogleAdsAssetRelationVideoQueue.php
Normal file
24
app/queue/redis/GoogleAdsAssetRelationVideoQueue.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use app\event\GoogleAdsAssetRelations;
|
||||
use Webman\Event\Event;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class GoogleAdsAssetRelationVideoQueue implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = GoogleAdsAssetRelations::video_queue;
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
// dump($this->queue.' consumed',$data);
|
||||
Event::emit(GoogleAdsAssetRelations::video_queue, $data);
|
||||
}
|
||||
|
||||
}
|
24
app/queue/redis/GoogleAdsCampaignQueue.php
Normal file
24
app/queue/redis/GoogleAdsCampaignQueue.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use app\event\GoogleAdsCampaigns;
|
||||
use Webman\Event\Event;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class GoogleAdsCampaignQueue implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = GoogleAdsCampaigns::queue;
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
// dump($this->queue.' consumed',$data);
|
||||
Event::emit(GoogleAdsCampaigns::queue, $data);
|
||||
}
|
||||
|
||||
}
|
26
app/queue/redis/GoogleAdsCustomerQueue.php
Normal file
26
app/queue/redis/GoogleAdsCustomerQueue.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use app\event\GoogleAdsCustomers;
|
||||
use Webman\Event\Event;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class GoogleAdsCustomerQueue implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = GoogleAdsCustomers::add_queue;
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
dump($this->queue.' consumed',$data);
|
||||
Event::emit(GoogleAdsCustomers::add_queue, $data);
|
||||
// 无需反序列化
|
||||
// var_export($data); // 输出 ['to' => 'tom@gmail.com', 'content' => 'hello']
|
||||
}
|
||||
|
||||
}
|
24
app/queue/redis/GoogleAdsDateDataQueue.php
Normal file
24
app/queue/redis/GoogleAdsDateDataQueue.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use app\event\GoogleAdsDateDatas;
|
||||
use Webman\Event\Event;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class GoogleAdsDateDataQueue implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = GoogleAdsDateDatas::queue;
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
// dump($this->queue.' consumed',$data);
|
||||
Event::emit(GoogleAdsDateDatas::queue, $data);
|
||||
}
|
||||
|
||||
}
|
24
app/queue/redis/GoogleAdsGroupQueue.php
Normal file
24
app/queue/redis/GoogleAdsGroupQueue.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\queue\redis;
|
||||
|
||||
use app\event\GoogleAdsGroups;
|
||||
use Webman\Event\Event;
|
||||
use Webman\RedisQueue\Consumer;
|
||||
|
||||
class GoogleAdsGroupQueue implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public $queue = GoogleAdsGroups::queue;
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public $connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume($data)
|
||||
{
|
||||
// dump($this->queue.' consumed',$data);
|
||||
Event::emit(GoogleAdsGroups::queue, $data);
|
||||
}
|
||||
|
||||
}
|
@ -6,6 +6,9 @@ use GuzzleHttp\Client;
|
||||
use think\facade\Db as ThinkDb;
|
||||
use app\model\ThirdUserAdvertiser;
|
||||
use app\model\ThirdUser;
|
||||
//use Webman\RedisQueue\Redis;
|
||||
use Webman\RedisQueue\Client as QueueClient;
|
||||
use app\event\GoogleAdsCustomers;
|
||||
|
||||
class GoogleOAuthService
|
||||
{
|
||||
@ -205,6 +208,10 @@ class GoogleOAuthService
|
||||
";
|
||||
}
|
||||
ThinkDb::execute($sql, $data);
|
||||
|
||||
$options = [];
|
||||
$options['data'] = $refreshToken;
|
||||
$this->queue($options);
|
||||
}
|
||||
|
||||
public function updateRefreshToken($refreshToken)
|
||||
@ -301,5 +308,20 @@ class GoogleOAuthService
|
||||
|
||||
}
|
||||
|
||||
public function queue($options = []): string
|
||||
{
|
||||
// 队列名
|
||||
$queue = GoogleAdsCustomers::add_queue;
|
||||
// 数据,可以直接传数组,无需序列化
|
||||
// $options = ['to' => 'tom@gmail.com', 'content' => 'hello'];
|
||||
// 投递消息
|
||||
// Redis::send($queue, $options['data']);
|
||||
QueueClient::send($queue, $options['data'],10); //异步投递 延后15秒
|
||||
// 投递延迟消息,消息会在60秒后处理
|
||||
// Redis::send($queue, $options['data'], 60);
|
||||
|
||||
return $queue.' redis queue ok';
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -20,28 +20,52 @@ return [
|
||||
// TiktokAdsDetails::type => [
|
||||
// [TiktokAdsDetails::class, 'update'],
|
||||
// ],
|
||||
GoogleAdsCampaigns::type => [
|
||||
|
||||
|
||||
GoogleAdsCampaigns::event => [
|
||||
[GoogleAdsCampaigns::class, 'syncCampaigns'],
|
||||
],
|
||||
GoogleAdsCampaigns::queue => [
|
||||
[GoogleAdsCampaigns::class, 'getCampaigns'],
|
||||
],
|
||||
GoogleAdsDateDatas::type => [
|
||||
[GoogleAdsDateDatas::class, 'getDateDatas'],
|
||||
GoogleAdsGroups::event => [
|
||||
[GoogleAdsGroups::class, 'syncGroups'],
|
||||
],
|
||||
GoogleAdsGroups::type => [
|
||||
GoogleAdsGroups::queue => [
|
||||
[GoogleAdsGroups::class, 'getGroups'],
|
||||
],
|
||||
GoogleAdsAds::type => [
|
||||
GoogleAdsAds::event => [
|
||||
[GoogleAdsAds::class, 'syncAds'],
|
||||
],
|
||||
GoogleAdsAds::queue => [
|
||||
[GoogleAdsAds::class, 'getAds'],
|
||||
],
|
||||
GoogleAdsAssets::type => [
|
||||
GoogleAdsAssets::event => [
|
||||
[GoogleAdsAssets::class, 'syncAssets'],
|
||||
],
|
||||
GoogleAdsAssets::queue => [
|
||||
[GoogleAdsAssets::class, 'getAssets'],
|
||||
],
|
||||
GoogleAdsAssetRelations::IMAGEASSET => [
|
||||
GoogleAdsAssetRelations::event => [
|
||||
[GoogleAdsAssetRelations::class, 'syncAssetRelations'],
|
||||
],
|
||||
GoogleAdsAssetRelations::queue => [
|
||||
[GoogleAdsAssetRelations::class, 'getAssetRelations'],
|
||||
],
|
||||
GoogleAdsAssetRelations::VIDEOASSET => [
|
||||
|
||||
GoogleAdsAssetRelations::video_queue => [
|
||||
[GoogleAdsAssetRelations::class, 'getVideoAssetRelations'],
|
||||
],
|
||||
GoogleAdsCustomers::CUSTOMERADD => [
|
||||
GoogleAdsDateDatas::event => [
|
||||
[GoogleAdsDateDatas::class, 'syncDateDatas'],
|
||||
],
|
||||
GoogleAdsDateDatas::queue => [
|
||||
[GoogleAdsDateDatas::class, 'getDateDatas'],
|
||||
],
|
||||
GoogleAdsCustomers::event => [
|
||||
[GoogleAdsCustomers::class, 'addCustomers'],
|
||||
],
|
||||
GoogleAdsCustomers::add_queue => [
|
||||
[GoogleAdsCustomers::class, 'addCustomers'],
|
||||
],
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
return [
|
||||
'consumer' => [
|
||||
'handler' => Webman\RedisQueue\Process\Consumer::class,
|
||||
'count' => 8, // 可以设置多进程同时消费
|
||||
'count' => 1, // 可以设置多进程同时消费
|
||||
'constructor' => [
|
||||
// 消费者类目录
|
||||
'consumer_dir' => app_path() . '/queue/redis'
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
return [
|
||||
'default' => [
|
||||
'host' => 'redis://127.0.0.1:6379',
|
||||
'host' => 'redis://'.env('REDIS_HOST').':6379',
|
||||
'options' => [
|
||||
'auth' => null, // 密码,字符串类型,可选参数
|
||||
'db' => 0, // 数据库
|
||||
|
Loading…
Reference in New Issue
Block a user