This commit is contained in:
Default
2025-03-15 20:12:21 +08:00
parent 105ffe11c7
commit eb9035a7ae
134 changed files with 15450 additions and 119 deletions

View File

@@ -0,0 +1,137 @@
<?php
declare(strict_types=1);
namespace app\task\collection\seo;
use app\task\collection\PullDataColBase;
use app\admin\model\VideoInfoModel;
use app\admin\model\SystemConfigModel;
use app\admin\model\VideoClassModel;
class GenerateSiteMapCol extends PullDataColBase
{
public function generate()
{
$strSiteDomain = SystemConfigModel::getValByCode('YONG_JIU_DOMAIN');
// 每个 Sitemap 包含的最大 URL 数量
$chunkSize = 40000;
// 从数据库获取所有视频总数
$totalVideoCount = VideoInfoModel::count();
// 获取分类信息
$categories = VideoClassModel::getDataByCache();
// 生成视频详情的 Sitemap
$videoSitemapFiles = $this->generateVideoSitemaps($chunkSize, $totalVideoCount, $strSiteDomain);
// 生成分类的 Sitemap
$categorySitemapFiles = $this->generateCategorySitemaps($categories, $strSiteDomain);
// 合并所有 Sitemap 文件路径
$allSitemapFiles = array_merge($videoSitemapFiles, $categorySitemapFiles);
// 生成 Sitemap Index 文件
$this->buildSitemapIndex($allSitemapFiles, $strSiteDomain);
var_dump(['message' => '所有 Sitemap 生成成功', 'files' => $allSitemapFiles]);
}
private function generateVideoSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$videos = VideoInfoModel::field('v_pinyin')
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildSitemap($videos, $strSiteDomain);
$filePath = public_path() . "sitemap_video_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function generateCategorySitemaps(array $categories, string $strSiteDomain): array
{
$sitemapFiles = [];
foreach ($categories as $category) {
$vcId = $category['vc_id'];
$vcNicheng = $category['vc_nicheng'];
$vcName = $category['vc_name'];
$videoCount = VideoInfoModel::where('vc_id', $vcId)->count();
$totalPages = ceil($videoCount / 30);
$categoryUrls = [];
$categoryUrls[] = [
'url' => "/vodtype/{$vcNicheng}.html",
'title' => "{$vcName} - 首页",
'is_home' => true,
];
for ($page = 2; $page <= $totalPages; $page++) {
$categoryUrls[] = [
'url' => "/vodshow/{$vcNicheng}--------{$page}---.html",
'title' => "{$vcName} - 第{$page}",
'is_home' => false,
];
}
$sitemapXml = $this->buildSitemap($categoryUrls, $strSiteDomain, true);
$filePath = public_path() . "sitemap_category_{$vcNicheng}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function buildSitemap(array $items, string $strSiteDomain, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/voddetail/' . htmlspecialchars($item['v_pinyin'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>0.8</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
private function buildSitemapIndex(array $sitemapFiles, string $strSiteDomain): void
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemapIndexStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemapIndexEnd = '</sitemapindex>';
$sitemapEntries = '';
foreach ($sitemapFiles as $file) {
$url = 'https://' . $strSiteDomain . '/' . basename($file);
$sitemapEntries .= '<sitemap>';
$sitemapEntries .= '<loc>' . htmlspecialchars($url, ENT_QUOTES) . '</loc>';
$sitemapEntries .= '<lastmod>' . date('Y-m-d') . '</lastmod>';
$sitemapEntries .= '</sitemap>';
}
$sitemapIndexXml = $xmlHeader . $sitemapIndexStart . $sitemapEntries . $sitemapIndexEnd;
file_put_contents(public_path() . 'sitemap_index.xml', $sitemapIndexXml);
var_dump(['message' => 'Sitemap Index 生成成功', 'file' => 'sitemap_index.xml']);
}
}

View File

@@ -0,0 +1,188 @@
<?php
declare(strict_types=1);
namespace app\task\collection\seo;
use app\task\collection\PullDataColBase;
use app\admin\model\XiaoShuoXiangQingModel;
use app\admin\model\XiaoShuoZhangJieModel;
use app\admin\model\SystemConfigModel;
use app\admin\model\SiteModel;
use app\admin\model\XiaoShuoFenLeiModel;
class GenerateSiteMapNovel extends PullDataColBase
{
public function generate()
{
$SiteModel = SiteModel::getValById(config('app.default_app_id'));
$strSiteDomain = $SiteModel['site_domain'];
$strFenleiPath = $SiteModel['site_fenlei_path'];
$strXqPath = $SiteModel['site_xiangqing_path'];
$strRankPath = $SiteModel['site_rank_path'];
$strTjPath = $SiteModel['site_tui_jian_path'];
$strSeoPath = $SiteModel['site_seo_path'];
$strZdyPath = $SiteModel['site_zdy_path'];
$strZjPath = $SiteModel['site_zhangjie_path'];
// 每个 Sitemap 包含的最大 URL 数量
$chunkSize = 40000;
// 从数据库获取所有总数
$totalNovelCount = XiaoShuoXiangQingModel::count();
// 从数据库获取所有总数
$totalNovelZjCount = XiaoShuoZhangJieModel::count();
// 获取分类信息
$categories = XiaoShuoFenLeiModel::getDataByCache();
// 生成详情的 Sitemap
$novelSitemapFiles = $this->generateNovelSitemaps($chunkSize, $totalNovelCount, $strSiteDomain);
// 生成章节的 Sitemap
$novelZjSitemapFiles = $this->generateNovelZjSitemaps($chunkSize, $totalNovelZjCount, $strSiteDomain);
// 生成分类的 Sitemap
$categorySitemapFiles = $this->generateCategorySitemaps($categories, $strSiteDomain);
// 合并所有 Sitemap 文件路径
$allSitemapFiles = array_merge($novelSitemapFiles, $categorySitemapFiles,$novelZjSitemapFiles);
// 生成 Sitemap Index 文件
$this->buildSitemapIndex($allSitemapFiles, $strSiteDomain);
var_dump(['message' => '所有 Sitemap 生成成功', 'files' => $allSitemapFiles]);
}
private function generateNovelZjSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoZhangJieModel::field(['xsxq_id','xszj_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildZjSitemap($Novels, $strSiteDomain);
$filePath = public_path() . "sitemap_novel_zj_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function generateNovelSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoXiangQingModel::field(['xsxq_id','xsxq_source_id','xsxq_source_seo_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildSitemap($Novels, $strSiteDomain);
$filePath = public_path() . "sitemap_novel_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function generateCategorySitemaps(array $categories, string $strSiteDomain): array
{
$sitemapFiles = [];
foreach ($categories as $category) {
$vcId = $category['xsfl_id'];
$vcName = $category['xsfl_name'];
$intNovelCount = XiaoShuoFenLeiModel::where('xsfl_id', $vcId)->count();
$totalPages = ceil($intNovelCount / 30);
$categoryUrls = [];
for ($type = 0; $type <= 3; $type++) {
for ($page = 1; $page <= $totalPages; $page++) {
$categoryUrls[] = [
// /fenlei/1-0-1.html
'url' => "/fenlei/{$vcId}-{$type}-{$page}.html",
'title' => "{$vcName} - 第{$page}",
'is_home' => false,
];
}
}
$sitemapXml = $this->buildSitemap($categoryUrls, $strSiteDomain, true);
$filePath = public_path() . "sitemap_category_{$vcId}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
private function buildZjSitemap(array $items, string $strSiteDomain, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// zj/18648-206.html
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/zj/' . htmlspecialchars($item['xsxq_id'].'-'.$item['xszj_id']. '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>0.8</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
private function buildSitemap(array $items, string $strSiteDomain, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/20052-16107-161071.html
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/xq/' . htmlspecialchars($item['xsxq_id'].'-'.$item['xsxq_source_id'].'-'.$item['xsxq_source_seo_id']. '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
private function buildSitemapIndex(array $sitemapFiles, string $strSiteDomain): void
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemapIndexStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemapIndexEnd = '</sitemapindex>';
$sitemapEntries = '';
foreach ($sitemapFiles as $file) {
$url = 'https://' . $strSiteDomain . '/' . basename($file);
$sitemapEntries .= '<sitemap>';
$sitemapEntries .= '<loc>' . htmlspecialchars($url, ENT_QUOTES) . '</loc>';
$sitemapEntries .= '<lastmod>' . date('Y-m-d') . '</lastmod>';
$sitemapEntries .= '</sitemap>';
}
$sitemapIndexXml = $xmlHeader . $sitemapIndexStart . $sitemapEntries . $sitemapIndexEnd;
file_put_contents(public_path() . 'sitemap_index.xml', $sitemapIndexXml);
var_dump(['message' => 'Sitemap Index 生成成功', 'file' => 'sitemap_index.xml']);
}
}

View File

@@ -0,0 +1,242 @@
<?php
declare(strict_types=1);
namespace app\task\collection\seo;
use app\task\collection\PullDataColBase;
use app\admin\model\XiaoShuoXiangQingModel;
use app\admin\model\NovelInfoSeoModel;
use app\admin\model\XiaoShuoZhangJieModel;
use app\admin\model\SiteModel;
use app\admin\model\XiaoShuoFenLeiModel;
class GenerateSiteMapNovelSk extends PullDataColBase
{
public function generate()
{
$SiteModel = SiteModel::getValById(config('app.default_app_id'));
// $strSiteDomain = SiteModel::getValBySiteIdByValCode('site_domain');
$strSiteDomain = $SiteModel['site_domain'];
$strFenleiPath = $SiteModel['site_fenlei_path'];
$strXqPath = $SiteModel['site_xiangqing_path'];
$strRankPath = $SiteModel['site_rank_path'];
$strTjPath = $SiteModel['site_tui_jian_path'];
$strSeoPath = $SiteModel['site_seo_path'];
$strZdyPath = $SiteModel['site_zdy_path'];
$strZjPath = $SiteModel['site_zhangjie_path'];
// 每个 Sitemap 包含的最大 URL 数量
$chunkSize = 40000;
// 从数据库获取所有总数
$totalNovelCount = XiaoShuoXiangQingModel::count();
// 从数据库获取所有总数
$totalNovelSeoCount = NovelInfoSeoModel::count();
// 从数据库获取所有总数
$totalNovelZjCount = XiaoShuoZhangJieModel::count();
// 获取分类信息
$categories = XiaoShuoFenLeiModel::getDataByCache();
// 生成详情的 Sitemap 小说详情
$novelSitemapFiles = $this->generateNovelSitemaps($chunkSize, $totalNovelCount, $strSiteDomain, $strXqPath);
// 生成详情的 Sitemap 小说seo
$novelSeoSitemapFiles = $this->generateNovelSeoSitemaps($chunkSize, $totalNovelSeoCount, $strSiteDomain, $strSeoPath);
// 生成章节的 Sitemap 小说章节
$novelZjSitemapFiles = $this->generateNovelZjSitemaps($chunkSize, $totalNovelZjCount, $strSiteDomain, $strXqPath);
// 生成分类的 Sitemap 小说分类
$categorySitemapFiles = $this->generateCategorySitemaps($categories, $strSiteDomain, $strFenleiPath, $strXqPath);
// 合并所有 Sitemap 文件路径
$allSitemapFiles = array_merge($novelSitemapFiles, $novelSeoSitemapFiles, $categorySitemapFiles, $novelZjSitemapFiles);
// 生成 Sitemap Index 文件
$this->buildSitemapIndex($allSitemapFiles, $strSiteDomain);
var_dump(['message' => '所有 Sitemap 生成成功', 'files' => $allSitemapFiles]);
}
# 生成小说章节 xml文件
private function generateNovelZjSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strXqPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoZhangJieModel::field(['xsxq_id', 'xszj_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildZjSitemap($Novels, $strSiteDomain, $strXqPath);
$filePath = public_path() . "sitemap_novel_zj_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
# 生成小说详情 xml文件
private function generateNovelSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strXqPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoXiangQingModel::field(['xsxq_id', 'xsxq_source_id', 'xsxq_source_seo_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildSitemap($Novels, $strSiteDomain, $strXqPath);
$filePath = public_path() . "sitemap_novel_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
# 生成小说详情 xml文件
private function generateNovelSeoSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strSeoPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = NovelInfoSeoModel::field(['xsxq_id', 'nis_id']) //show/nis_id
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildXiaoShuoSeoSitemap($Novels, $strSiteDomain, $strSeoPath);
$filePath = public_path() . "sitemap_novel_seo_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
// 生成分类链接
private function generateCategorySitemaps(array $categories, string $strSiteDomain, string $strFenleiPath, string $strXqPath): array
{
$sitemapFiles = [];
foreach ($categories as $category) {
$vcId = $category['xsfl_id'];
$vcName = $category['xsfl_name'];
$intNovelCount = XiaoShuoFenLeiModel::where('xsfl_id', $vcId)->count();
$totalPages = ceil($intNovelCount / 30);
$categoryUrls = [];
for ($status = 0; $status <= 2; $status++) {
for ($sort = 0; $sort <= 4; $sort++) {
for ($page = 1; $page <= $totalPages; $page++) {
$categoryUrls[] = [
// /fl/:intCId-:intSort-[:intPage]
'url' => "/{$strFenleiPath}/{$vcId}-{$sort}-{$page}.html",
'title' => "{$vcName} - 第{$page}",
'is_home' => false,
];
}
}
}
$sitemapXml = $this->buildSitemap($categoryUrls, $strSiteDomain, $strXqPath, true);
$filePath = public_path() . "sitemap_category_{$vcId}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
//生成章节链接
private function buildZjSitemap(array $items, string $strSiteDomain, string $strXqPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/:intNovelId/:intZhangJiePaiXu-[:strSort]
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strXqPath . '/' . htmlspecialchars($item['xsxq_id'] . '-' . $item['xszj_pai_xu']. '-' . $item['xszj_sort'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>0.8</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成 详情链接
private function buildSitemap(array $items, string $strSiteDomain, string $strXqPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/:intNovelId
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strXqPath . '/' . htmlspecialchars($item['xsxq_id'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成详情 seo 链接
private function buildXiaoShuoSeoSitemap(array $items, string $strSiteDomain, string $strSeoPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /show/:intNovelId
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strSeoPath . '/' . htmlspecialchars($item['nis_id'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成 xml 文件
private function buildSitemapIndex(array $sitemapFiles, string $strSiteDomain): void
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemapIndexStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemapIndexEnd = '</sitemapindex>';
$sitemapEntries = '';
foreach ($sitemapFiles as $file) {
$url = 'https://' . $strSiteDomain . '/' . basename($file);
$sitemapEntries .= '<sitemap>';
$sitemapEntries .= '<loc>' . htmlspecialchars($url, ENT_QUOTES) . '</loc>';
$sitemapEntries .= '<lastmod>' . date('Y-m-d') . '</lastmod>';
$sitemapEntries .= '</sitemap>';
}
$sitemapIndexXml = $xmlHeader . $sitemapIndexStart . $sitemapEntries . $sitemapIndexEnd;
file_put_contents(public_path() . 'sitemap_index.xml', $sitemapIndexXml);
var_dump(['message' => 'Sitemap Index 生成成功', 'file' => 'sitemap_index.xml']);
}
}

View File

@@ -0,0 +1,242 @@
<?php
declare(strict_types=1);
namespace app\task\collection\seo;
use app\task\collection\PullDataColBase;
use app\admin\model\XiaoShuoXiangQingModel;
use app\admin\model\NovelInfoSeoModel;
use app\admin\model\XiaoShuoZhangJieModel;
use app\admin\model\SiteModel;
use app\admin\model\XiaoShuoFenLeiModel;
class GenerateSiteMapNovelZw extends PullDataColBase
{
public function generate()
{
$SiteModel = SiteModel::getValById(config('app.default_app_id'));
// $strSiteDomain = SiteModel::getValBySiteIdByValCode('site_domain');
$strSiteDomain = $SiteModel['site_domain'];
$strFenleiPath = $SiteModel['site_fenlei_path'];
$strXqPath = $SiteModel['site_xiangqing_path'];
$strRankPath = $SiteModel['site_rank_path'];
$strTjPath = $SiteModel['site_tui_jian_path'];
$strSeoPath = $SiteModel['site_seo_path'];
$strZdyPath = $SiteModel['site_zdy_path'];
$strZjPath = $SiteModel['site_zhangjie_path'];
// 每个 Sitemap 包含的最大 URL 数量
$chunkSize = 40000;
// 从数据库获取所有总数
$totalNovelCount = XiaoShuoXiangQingModel::count();
// 从数据库获取所有总数
$totalNovelSeoCount = NovelInfoSeoModel::count();
// 从数据库获取所有总数
$totalNovelZjCount = XiaoShuoZhangJieModel::count();
// 获取分类信息
$categories = XiaoShuoFenLeiModel::getDataByCache();
// 生成详情的 Sitemap 小说详情
$novelSitemapFiles = $this->generateNovelSitemaps($chunkSize, $totalNovelCount, $strSiteDomain, $strXqPath);
// 生成详情的 Sitemap 小说seo
$novelSeoSitemapFiles = $this->generateNovelSeoSitemaps($chunkSize, $totalNovelSeoCount, $strSiteDomain, $strSeoPath);
// 生成章节的 Sitemap 小说章节
$novelZjSitemapFiles = $this->generateNovelZjSitemaps($chunkSize, $totalNovelZjCount, $strSiteDomain, $strXqPath);
// 生成分类的 Sitemap 小说分类
$categorySitemapFiles = $this->generateCategorySitemaps($categories, $strSiteDomain, $strFenleiPath, $strXqPath);
// 合并所有 Sitemap 文件路径
$allSitemapFiles = array_merge($novelSitemapFiles, $novelSeoSitemapFiles, $categorySitemapFiles, $novelZjSitemapFiles);
// 生成 Sitemap Index 文件
$this->buildSitemapIndex($allSitemapFiles, $strSiteDomain);
var_dump(['message' => '所有 Sitemap 生成成功', 'files' => $allSitemapFiles]);
}
# 生成小说章节 xml文件
private function generateNovelZjSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strXqPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoZhangJieModel::field(['xsxq_id', 'xszj_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildZjSitemap($Novels, $strSiteDomain, $strXqPath);
$filePath = public_path() . "sitemap_novel_zj_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
# 生成小说详情 xml文件
private function generateNovelSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strXqPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = XiaoShuoXiangQingModel::field(['xsxq_id', 'xsxq_source_id', 'xsxq_source_seo_id']) //intNovelId-:intNovelSourceId-:intNovelSourceSeoId
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildSitemap($Novels, $strSiteDomain, $strXqPath);
$filePath = public_path() . "sitemap_novel_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
# 生成小说详情 xml文件
private function generateNovelSeoSitemaps(int $chunkSize, int $totalCount, string $strSiteDomain, string $strSeoPath): array
{
$totalFiles = ceil($totalCount / $chunkSize);
$sitemapFiles = [];
for ($i = 0; $i < $totalFiles; $i++) {
$Novels = NovelInfoSeoModel::field(['xsxq_id', 'nis_id']) //show/nis_id
->limit($i * $chunkSize, $chunkSize)
->select()
->toArray();
$sitemapXml = $this->buildXiaoShuoSeoSitemap($Novels, $strSiteDomain, $strSeoPath);
$filePath = public_path() . "sitemap_novel_seo_{$i}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
// 生成分类链接
private function generateCategorySitemaps(array $categories, string $strSiteDomain, string $strFenleiPath, string $strXqPath): array
{
$sitemapFiles = [];
foreach ($categories as $category) {
$vcId = $category['xsfl_id'];
$vcName = $category['xsfl_name'];
$intNovelCount = XiaoShuoFenLeiModel::where('xsfl_id', $vcId)->count();
$totalPages = ceil($intNovelCount / 30);
$categoryUrls = [];
for ($status = 0; $status <= 2; $status++) {
for ($sort = 0; $sort <= 4; $sort++) {
for ($page = 1; $page <= $totalPages; $page++) {
$categoryUrls[] = [
// /fl/:intCId-:intSort-[:intPage]
'url' => "/{$strFenleiPath}/{$vcId}-{$sort}-{$page}.html",
'title' => "{$vcName} - 第{$page}",
'is_home' => false,
];
}
}
}
$sitemapXml = $this->buildSitemap($categoryUrls, $strSiteDomain, $strXqPath, true);
$filePath = public_path() . "sitemap_category_{$vcId}.xml";
file_put_contents($filePath, $sitemapXml);
$sitemapFiles[] = $filePath;
}
return $sitemapFiles;
}
//生成章节链接
private function buildZjSitemap(array $items, string $strSiteDomain, string $strXqPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/:intNovelId/:intZhangJiePaiXu-[:strSort]
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strXqPath . '/' . htmlspecialchars($item['xsxq_id'] . '-' . $item['xszj_pai_xu']. '-' . $item['xszj_sort'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>0.8</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成 详情链接
private function buildSitemap(array $items, string $strSiteDomain, string $strXqPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /xq/:intNovelId
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strXqPath . '/' . htmlspecialchars($item['xsxq_id'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成详情 seo 链接
private function buildXiaoShuoSeoSitemap(array $items, string $strSiteDomain, string $strSeoPath, bool $isCategory = false): string
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$urlsetStart = '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$urlsetEnd = '</urlset>';
// /show/:intNovelId
$urlEntries = '';
foreach ($items as $item) {
$urlEntries .= '<url>';
$urlEntries .= '<loc>https://' . $strSiteDomain . ($isCategory ? $item['url'] : '/' . $strSeoPath . '/' . htmlspecialchars($item['nis_id'] . '.html', ENT_QUOTES)) . '</loc>';
$urlEntries .= '<changefreq>daily</changefreq>';
$urlEntries .= '<priority>1.0</priority>';
$urlEntries .= '</url>';
}
return $xmlHeader . $urlsetStart . $urlEntries . $urlsetEnd;
}
// 生成 xml 文件
private function buildSitemapIndex(array $sitemapFiles, string $strSiteDomain): void
{
$xmlHeader = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemapIndexStart = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemapIndexEnd = '</sitemapindex>';
$sitemapEntries = '';
foreach ($sitemapFiles as $file) {
$url = 'https://' . $strSiteDomain . '/' . basename($file);
$sitemapEntries .= '<sitemap>';
$sitemapEntries .= '<loc>' . htmlspecialchars($url, ENT_QUOTES) . '</loc>';
$sitemapEntries .= '<lastmod>' . date('Y-m-d') . '</lastmod>';
$sitemapEntries .= '</sitemap>';
}
$sitemapIndexXml = $xmlHeader . $sitemapIndexStart . $sitemapEntries . $sitemapIndexEnd;
file_put_contents(public_path() . 'sitemap_index.xml', $sitemapIndexXml);
var_dump(['message' => 'Sitemap Index 生成成功', 'file' => 'sitemap_index.xml']);
}
}