初始化创建定时任务
This commit is contained in:
parent
bd0b06ee30
commit
1eec1d05f4
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,5 +4,3 @@
|
|||||||
/vendor
|
/vendor
|
||||||
*.log
|
*.log
|
||||||
.env
|
.env
|
||||||
/tests/tmp
|
|
||||||
/tests/.phpunit.result.cache
|
|
||||||
|
225
app/event/TiktokAds.php
Normal file
225
app/event/TiktokAds.php
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\event;
|
||||||
|
|
||||||
|
use app\model\TiktokAd;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
use support\Db;
|
||||||
|
use QL\QueryList;
|
||||||
|
use support\Redis;
|
||||||
|
|
||||||
|
|
||||||
|
class TiktokAds
|
||||||
|
{
|
||||||
|
//微博热榜地址
|
||||||
|
// 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 = 'tiktokads';
|
||||||
|
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"];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每天爬取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") ;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
184
app/event/TiktokAdsDetails.php
Normal file
184
app/event/TiktokAdsDetails.php
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\event;
|
||||||
|
|
||||||
|
use app\model\TiktokAdsDetail;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
use support\Db;
|
||||||
|
use QL\QueryList;
|
||||||
|
use support\Redis;
|
||||||
|
|
||||||
|
|
||||||
|
class TiktokAdsDetails
|
||||||
|
{
|
||||||
|
|
||||||
|
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 url = 'https://library.tiktok.com/api/v1/items';
|
||||||
|
|
||||||
|
const type = 'tiktokadsdetails';
|
||||||
|
|
||||||
|
|
||||||
|
// 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"];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每天爬取tiktok广告详情
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function update()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$client = new Client([
|
||||||
|
//允许重定向
|
||||||
|
// 'allow_redirects' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
$adIdCache = Redis::lPop(TiktokAds::type . 'AdsIds');
|
||||||
|
if (empty($adIdCache)) {
|
||||||
|
dump('获取AD id 异常:');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentParams = ['ad_id' => $adIdCache,'action' => 'details'];
|
||||||
|
|
||||||
|
$environment = 'vvv';
|
||||||
|
$proxyIp = '103.122.176.175';
|
||||||
|
$proxyPort = '31186';
|
||||||
|
$proxyUser = 'B978321E';
|
||||||
|
$proxyPassword = '1EC4E3C7398F';
|
||||||
|
|
||||||
|
$proxyAuth = base64_encode($proxyUser . ":" . $proxyPassword);
|
||||||
|
$options = [
|
||||||
|
"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=CfAlWGYPInwi1oHk0kTm68d0p21YS3UZ31sOR60H2uVC7A20NL46YHkF9z36OOlKC9XHODO2%2Biet2kk486i6SmO0TcqGntq1CbgwSqOH6f4ZES7jiHeI0mu82CKUVg%3D%3D',
|
||||||
|
'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,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
if($environment !== 'env') {
|
||||||
|
$options["headers"]["Proxy-Authorization"] = "Basic " . $proxyAuth;
|
||||||
|
$options["proxy"] = $proxyIp . ':' . $proxyPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = json_decode($client->request('Get', self::url.'/'.$currentParams['ad_id'].'/'.$currentParams['action'], $options)->getBody()->getContents(), true);
|
||||||
|
// dump($res);return; //调试点
|
||||||
|
|
||||||
|
|
||||||
|
if (empty($res['data']) || $res['code'] != 0) {
|
||||||
|
dump('更新tiktok Ads Details接口响应异常:' . json_encode($res, JSON_UNESCAPED_UNICODE));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ad = $res['data'];
|
||||||
|
if( $ad['ad']['audit_status'] == 2 || empty( $ad['ad']['videos'])){
|
||||||
|
return; //审核不过或者没视频不采集
|
||||||
|
}
|
||||||
|
$imagesJson = is_array($ad['ad']['image_urls']) ? json_encode($ad['ad']['image_urls']):json_encode([]);
|
||||||
|
$targetingLocationJson = is_array($ad['targeting']['location']) ? json_encode($ad['targeting']['location']):json_encode([]);
|
||||||
|
$targetingAgeJson = is_array($ad['targeting']['age']) ? json_encode($ad['targeting']['age']):json_encode([]);
|
||||||
|
$targetingGenderJson = is_array($ad['targeting']['gender']) ? json_encode($ad['targeting']['gender']):json_encode([]);
|
||||||
|
|
||||||
|
// dump($rejection_info);
|
||||||
|
$insertData[$ad['ad']['id']] = [
|
||||||
|
'ad_id' => $ad['ad']['id'],
|
||||||
|
'ad_name' => $ad['ad']['name'],
|
||||||
|
'audit_status' => $ad['ad']['audit_status'],
|
||||||
|
'ad_type' => $ad['ad']['type'],
|
||||||
|
'first_shown_date' => $ad['ad']['first_shown_date'],
|
||||||
|
'last_shown_date' => $ad['ad']['last_shown_date'],
|
||||||
|
|
||||||
|
'estimated_audience' => $ad['ad']['estimated_audience'],
|
||||||
|
'spent' => $ad['ad']['spent'],
|
||||||
|
'impression' => $ad['ad']['impression'],
|
||||||
|
'show_mode' => $ad['ad']['show_mode'],
|
||||||
|
'sor_audit_status' => $ad['ad']['sor_audit_status'],
|
||||||
|
'image_urls' => $imagesJson,
|
||||||
|
|
||||||
|
'advertiser_name' => $ad['advertiser']['name'],
|
||||||
|
'adv_biz_ids' => $ad['advertiser']['adv_biz_ids'],
|
||||||
|
'registry_location' => $ad['advertiser']['registry_location'],
|
||||||
|
'sponsor' => $ad['advertiser']['sponsor'],
|
||||||
|
|
||||||
|
'targeting_location' => $targetingLocationJson,
|
||||||
|
'targeting_age' => $targetingAgeJson,
|
||||||
|
'targeting_gender' => $targetingGenderJson,
|
||||||
|
'target_audience_size' => $ad['targeting']['target_audience_size'],
|
||||||
|
'audience_type' => $ad['targeting']['audience'],
|
||||||
|
'interest' => $ad['targeting']['interest'],
|
||||||
|
'video_interactions' => $ad['targeting']['video_interactions'],
|
||||||
|
'creator_interactions' => $ad['targeting']['creator_interactions'],
|
||||||
|
|
||||||
|
];
|
||||||
|
if(isset($ad['ad']['videos']) && !empty($ad['ad']['videos'])) {
|
||||||
|
// 遍历 "videos" 数组
|
||||||
|
foreach ($ad['ad']['videos'] as $video) {
|
||||||
|
$insertData[$ad['ad']['id']]['video_url'] = $video['video_url'];
|
||||||
|
$insertData[$ad['ad']['id']]['cover_img'] = $video['cover_img'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// dump($insertData);return;
|
||||||
|
|
||||||
|
if (empty($insertData)) return;
|
||||||
|
|
||||||
|
//开启事务
|
||||||
|
Db::beginTransaction();
|
||||||
|
|
||||||
|
|
||||||
|
//删除原来的旧数据
|
||||||
|
TiktokAdsDetail::query()->where('ad_id', $currentParams['ad_id'])->delete();
|
||||||
|
//添加新的数据
|
||||||
|
TiktokAdsDetail::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);
|
||||||
|
|
||||||
|
|
||||||
|
//提交事务
|
||||||
|
Db::commit();
|
||||||
|
//销毁$res
|
||||||
|
unset($res);
|
||||||
|
|
||||||
|
dump(date('Y-m-d H:i:s') . '更新' . self::type . '成功');
|
||||||
|
} catch (GuzzleException|\Exception $exception) {
|
||||||
|
//回滚事务
|
||||||
|
Db::rollBack();
|
||||||
|
dump('更' . self::type . '的广告ID为 '.$currentParams['ad_id'].' 异常:' . $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") ;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
54
app/process/UpdateGoogleAdsTask.php
Normal file
54
app/process/UpdateGoogleAdsTask.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\process;
|
||||||
|
|
||||||
|
|
||||||
|
use app\event\TiktokAds;
|
||||||
|
use app\event\TiktokAdsDetails;
|
||||||
|
use Webman\Event\Event;
|
||||||
|
use Workerman\Crontab\Crontab;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新热搜列表任务
|
||||||
|
*/
|
||||||
|
class UpdateGoogleAdsTask
|
||||||
|
{
|
||||||
|
//错开时间执行,否则固定时间段接口会响应很慢
|
||||||
|
public function onWorkerStart()
|
||||||
|
{
|
||||||
|
|
||||||
|
// 每15分钟执行一次
|
||||||
|
new Crontab('*/15 * * * * *', function () {
|
||||||
|
|
||||||
|
// dump(date('Y-m-d H:i:s') . '更新' . TiktokAdsDetails::type . '开始');
|
||||||
|
// Event::emit(TiktokAdsDetails::type, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 每12分钟执行一次
|
||||||
|
new Crontab('0 */12 * * * *', function () {
|
||||||
|
// dump(date('Y-m-d H:i:s') . '更新' . HuPu::type . '开始');
|
||||||
|
// Event::emit(HuPu::type, null);
|
||||||
|
|
||||||
|
// dump(date('Y-m-d H:i:s') . '更新' . DouBan::type . '开始');
|
||||||
|
// Event::emit(DouBan::type, null);
|
||||||
|
//
|
||||||
|
// dump(date('Y-m-d H:i:s') . '更新' . Itzhijia::type . '开始');
|
||||||
|
// Event::emit(Itzhijia::type, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 每30分钟执行一次
|
||||||
|
// new Crontab('0 */30 * * * *', function () {
|
||||||
|
// dump(date('Y-m-d H:i:s') . '更新' . V2ex::type . '开始');
|
||||||
|
// Event::emit(V2ex::type, null);
|
||||||
|
//
|
||||||
|
// dump(date('Y-m-d H:i:s') . '更新' . GitHub::type . '开始');
|
||||||
|
// Event::emit(GitHub::type, null);
|
||||||
|
//
|
||||||
|
// dump(date('Y-m-d H:i:s') . '更新' . JueJin::type . '开始');
|
||||||
|
// Event::emit(JueJin::type, null);
|
||||||
|
// });
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,11 @@
|
|||||||
"webman/auto-route": "^1.0",
|
"webman/auto-route": "^1.0",
|
||||||
"psr/container": "^1.1.1",
|
"psr/container": "^1.1.1",
|
||||||
"php-di/php-di": "^6.3",
|
"php-di/php-di": "^6.3",
|
||||||
"doctrine/annotations": "^1.14"
|
"doctrine/annotations": "^1.14",
|
||||||
|
"webman/redis-queue": "^1.3",
|
||||||
|
"webman/event": "^1.0",
|
||||||
|
"workerman/crontab": "^1.0",
|
||||||
|
"illuminate/redis": "^10.48"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-event": "For better performance. "
|
"ext-event": "For better performance. "
|
||||||
|
1068
composer.lock
generated
1068
composer.lock
generated
File diff suppressed because it is too large
Load Diff
17
config/event.php
Normal file
17
config/event.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
use app\event\TiktokAds;
|
||||||
|
use app\event\TiktokAdsDetails;
|
||||||
|
|
||||||
|
|
||||||
|
return [
|
||||||
|
//知乎热榜
|
||||||
|
TiktokAds::type => [
|
||||||
|
[TiktokAds::class, 'update'],
|
||||||
|
],
|
||||||
|
TiktokAdsDetails::type => [
|
||||||
|
[TiktokAdsDetails::class, 'update'],
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
4
config/plugin/webman/event/app.php
Normal file
4
config/plugin/webman/event/app.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'enable' => true,
|
||||||
|
];
|
17
config/plugin/webman/event/bootstrap.php
Normal file
17
config/plugin/webman/event/bootstrap.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of webman.
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @author walkor<walkor@workerman.net>
|
||||||
|
* @copyright walkor<walkor@workerman.net>
|
||||||
|
* @link http://www.workerman.net/
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
return [
|
||||||
|
Webman\Event\BootStrap::class,
|
||||||
|
];
|
7
config/plugin/webman/event/command.php
Normal file
7
config/plugin/webman/event/command.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Webman\Event\EventListCommand;
|
||||||
|
|
||||||
|
return [
|
||||||
|
EventListCommand::class
|
||||||
|
];
|
4
config/plugin/webman/redis-queue/app.php
Normal file
4
config/plugin/webman/redis-queue/app.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'enable' => true,
|
||||||
|
];
|
7
config/plugin/webman/redis-queue/command.php
Normal file
7
config/plugin/webman/redis-queue/command.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Webman\RedisQueue\Command\MakeConsumerCommand;
|
||||||
|
|
||||||
|
return [
|
||||||
|
MakeConsumerCommand::class
|
||||||
|
];
|
32
config/plugin/webman/redis-queue/log.php
Normal file
32
config/plugin/webman/redis-queue/log.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of webman.
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @author walkor<walkor@workerman.net>
|
||||||
|
* @copyright walkor<walkor@workerman.net>
|
||||||
|
* @link http://www.workerman.net/
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default' => [
|
||||||
|
'handlers' => [
|
||||||
|
[
|
||||||
|
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||||
|
'constructor' => [
|
||||||
|
runtime_path() . '/logs/redis-queue/queue.log',
|
||||||
|
7, //$maxFiles
|
||||||
|
Monolog\Logger::DEBUG,
|
||||||
|
],
|
||||||
|
'formatter' => [
|
||||||
|
'class' => Monolog\Formatter\LineFormatter::class,
|
||||||
|
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
],
|
||||||
|
]
|
||||||
|
];
|
11
config/plugin/webman/redis-queue/process.php
Normal file
11
config/plugin/webman/redis-queue/process.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'consumer' => [
|
||||||
|
'handler' => Webman\RedisQueue\Process\Consumer::class,
|
||||||
|
'count' => 8, // 可以设置多进程同时消费
|
||||||
|
'constructor' => [
|
||||||
|
// 消费者类目录
|
||||||
|
'consumer_dir' => app_path() . '/queue/redis'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
13
config/plugin/webman/redis-queue/redis.php
Normal file
13
config/plugin/webman/redis-queue/redis.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'default' => [
|
||||||
|
'host' => 'redis://127.0.0.1:6379',
|
||||||
|
'options' => [
|
||||||
|
'auth' => null, // 密码,字符串类型,可选参数
|
||||||
|
'db' => 0, // 数据库
|
||||||
|
'prefix' => '', // key 前缀
|
||||||
|
'max_attempts' => 5, // 消费失败后,重试次数
|
||||||
|
'retry_seconds' => 5, // 重试间隔,单位秒
|
||||||
|
]
|
||||||
|
],
|
||||||
|
];
|
@ -58,5 +58,9 @@ return [
|
|||||||
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
|
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
],
|
||||||
|
|
||||||
|
'updateGoogleAdsList' => [
|
||||||
|
'handler' => app\process\UpdateGoogleAdsTask::class
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'default' => [
|
'default' => [
|
||||||
'host' => '127.0.0.1',
|
'host' => getenv('REDIS_HOST'),
|
||||||
'password' => null,
|
'password' => getenv('REDIS_PASSWORD'),
|
||||||
'port' => 6379,
|
'port' => 6379,
|
||||||
'database' => 0,
|
'database' => 9,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user