- Google Trends RSS 기반 실시간 급상승 키워드 수집 서비스 추가 - 트렌딩 컨텍스트 활용 후킹 제목 생성 (5패턴: 충격/비교/숫자/질문/반전) - Veo 3.1 공식 가이드 기반 visual_prompt 5요소 프레임워크 적용 - GET /video/veo3/trending 엔드포인트 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100 lines
2.9 KiB
PHP
100 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Video;
|
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class TrendingKeywordService
|
|
{
|
|
private const CACHE_KEY = 'google_trends_kr';
|
|
|
|
private const CACHE_TTL = 1800; // 30분
|
|
|
|
private const RSS_URL = 'https://trends.google.co.kr/trending/rss?geo=KR';
|
|
|
|
/**
|
|
* Google Trends RSS에서 한국 실시간 급상승 키워드 수집
|
|
*/
|
|
public function fetchTrendingKeywords(int $limit = 10): array
|
|
{
|
|
return Cache::remember(self::CACHE_KEY, self::CACHE_TTL, function () use ($limit) {
|
|
try {
|
|
$response = Http::timeout(10)
|
|
->withHeaders(['Accept' => 'application/xml'])
|
|
->get(self::RSS_URL);
|
|
|
|
if (! $response->successful()) {
|
|
Log::warning('TrendingKeywordService: RSS 호출 실패', [
|
|
'status' => $response->status(),
|
|
]);
|
|
|
|
return [];
|
|
}
|
|
|
|
$keywords = $this->parseGoogleTrendsRss($response->body());
|
|
|
|
return array_slice($keywords, 0, $limit);
|
|
} catch (\Exception $e) {
|
|
Log::error('TrendingKeywordService: 예외 발생', [
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
|
|
return [];
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* RSS XML 파싱
|
|
*/
|
|
private function parseGoogleTrendsRss(string $xml): array
|
|
{
|
|
$keywords = [];
|
|
|
|
try {
|
|
// XML namespace 처리를 위해 ht: 접두사 등록
|
|
$doc = new \SimpleXMLElement($xml);
|
|
$namespaces = $doc->getNamespaces(true);
|
|
|
|
$items = $doc->channel->item ?? [];
|
|
|
|
foreach ($items as $item) {
|
|
$keyword = (string) $item->title;
|
|
|
|
if (empty($keyword)) {
|
|
continue;
|
|
}
|
|
|
|
$traffic = '';
|
|
$newsTitle = '';
|
|
|
|
if (isset($namespaces['ht'])) {
|
|
$htData = $item->children($namespaces['ht']);
|
|
$traffic = (string) ($htData->approx_traffic ?? '');
|
|
|
|
if (isset($htData->news_item)) {
|
|
$newsTitle = (string) ($htData->news_item->news_item_title ?? '');
|
|
}
|
|
}
|
|
|
|
$pubDate = (string) ($item->pubDate ?? '');
|
|
|
|
$keywords[] = [
|
|
'keyword' => $keyword,
|
|
'traffic' => $traffic,
|
|
'news_title' => $newsTitle,
|
|
'pub_date' => $pubDate ? date('c', strtotime($pubDate)) : null,
|
|
];
|
|
}
|
|
} catch (\Exception $e) {
|
|
Log::error('TrendingKeywordService: XML 파싱 실패', [
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
|
|
return $keywords;
|
|
}
|
|
}
|