需求描述
在SEO优化中,由于部分搜索引起(如神马、搜狗)没有自动推送功能,导致主动提交网站链接过于麻烦,而通过生成sitemap
可以简洁高效的提交链接,让搜索引擎及时收录。
实践步骤
创建sitemap
1. 安装laravel-sitemap
扩展包:
composer require spatie/laravel-sitemap
(在GitHub
上查看laravel-sitemap)
2. 创建一个SitemapService
编写生成逻辑
示例代码:
<?php
namespace App\Services;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\SitemapIndex;
class SitemapService
{
//生成文章子文件,考虑文章数量可能很多,所以分周或者分月汇总
public function buildArticles()
{
$sitemapName = '';
$articlesData = [];
Article::select(['id', 'created_at', 'updated_at'])->chunk(100, function ($articles) use (&$articlesData, &$sitemapName) {
foreach ($articles as $article) {
$created_at = $article->created_at;
$sitemapName = $created_at->year . '-' . sprintf("%02d", $created_at->week());
$articlesData[$sitemapName][] = [
'url' => route('article.show', ['id' => $article->id]),
'lastmod' => $article->updated_at,
];
}
});
$lastModTimes = [];
foreach ($articlesData as $name => $data) {
$sitemap = Sitemap::create();
$lastModTime = max(Arr::pluck($data, 'lastmod'));
foreach ($data as $_data) {
$sitemap->add(Url::create($_data['url'])
->setLastModificationDate($_data['lastmod']));
}
if ($this->writeSiteMap($sitemap, '/sitemap/articles-' . $name . '.xml')) {
$lastModTimes[$name] = $lastModTime;
}
}
return $lastModTimes;
}
//生成标签地图文件,标签一般不会过多,放在一个文件中即可
public function buildTags()
{
$sitemap = Sitemap::create();
$lastModTime = Carbon::parse('2000-01-01 12:00');
Tag::chunk(100, function ($tags) use ($sitemap, &$lastModTime) {
$lastModTime = max($tags->pluck('updated_at')->toArray());
foreach ($tags as $tag) {
$sitemap->add(Url::create(route('tags.show', [ 'id' => $tag->id]))
->setLastModificationDate($tag->updated_at)
->setChangeFrequency(Url::CHANGE_FREQUENCY_WEEKLY)
);
}
});
if ($this->writeSiteMap($sitemap, '/sitemap/tags.xml')) {
return $lastModTime;
}
return false;
}
//生成各栏目首页地图文件
public function buildHome()
{
$sitemap = Sitemap::create();
//官网首页
$sitemap->add(Url::create('/')->setLastModificationDate(now()));
//帮助首页
$sitemap->add(Url::create(route('help.index'))->setLastModificationDate(now()));
return $this->writeSiteMap($sitemap, '/sitemap/home.xml');
}
public function buildIndex()
{
// create sitemap index
$sitemap = SitemapIndex::create();
//各栏目首页
if ($this->buildHome()) {
$sitemap->add(\Spatie\Sitemap\Tags\Sitemap::create('/sitemap/home.xml')
->setLastModificationDate(now()));
}
//标签
if ($lastModTime = $this->buildTags()) {
$sitemap->add(\Spatie\Sitemap\Tags\Sitemap::create('/sitemap/tags.xml')
->setLastModificationDate($lastModTime));
}
//文章
if ($lastModTimes = $this->buildArticles()) {
foreach ($lastModTimes as $name => $time) {
$sitemap->add(\Spatie\Sitemap\Tags\Sitemap::create('/sitemap/articles-' . $name . '.xml')
->setLastModificationDate($time));
}
}
$this->writeSiteMap($sitemap, 'sitemap.xml');
}
protected function writeSiteMap($sitemap, $path)
{
try {
$sitemap->writeToFile(public_path($path));
} catch (\Exception $exception) {
Log::error('生成sitemap失败(' . $path . '):' . $exception->getMessage());
return false;
}
return true;
}
}
3. 生成sitemap文件
可食用任务调度每日更新:
php artisan make:command CreateSiteMap
示例代码:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\SitemapService;
class CreateSiteMap extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'Create:sitemap';
/**
* The console command description.
*
* @var string
*/
protected $description = 'create sitemap';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('[' . now() . ']开始执行sitemap生成脚本');
try {
$sitemapService = new SitemapService();
$sitemapService->buildIndex();
} catch (\Exception $exception) {
$this->error('生成sitemap失败:' . $exception->getMessage());
return;
}
$this->info('[' . now() . ']生成sitemap成功!');
}
}
在Kernel
中添加任务:
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
…………
\App\Console\Commands\CreateSiteMap::class,
…………
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
…………
//创建站点地图
$schedule->command('Create:sitemap')
->dailyAt('05:00')
->runInBackground();
…………
}
…………
}
4. 创建小结
通过以上方法,我们就在应用根目录下生成了sitemao.xml
的索引文件,在文件中添加了各个板块或分时段的url明细。这样可以保证sitemap
文件不会日积月累,超过限制大小和url数量。
提交sitemap
1. 国内支持sitemap
提交的搜索引擎
至于搜狗搜索,站长平台没有显式sitemap
提交方式,不过访问http://zhanzhang.sogou.com/index.php/sitemap/create/id/你的ID
也是可以提交的。
获取搜狗站点ID可以在网站支持
,右键查看源代码,如下图获取:
2. 在网站robots.txt
添加Sitemap
字段,方便蜘蛛爬取
robots.txt
结构如下:
建议在robots.txt
文件最后添加以下信息:
Sitemap: the/url/to/your/stemap.xml
总结说明
昨天刚开始想要弄sitemap
看了各种说明,因为对其不了解,觉得很复杂,单实际做了一遍后,会发现并不是很麻烦。
所以,当我们看到问题后,尝试一步步去解决,自然能优化到你想要的结果。
而畏惧前行,也只能故步自封。
另外提醒,sitemap
提交并不会比主动推动或自动提交优秀,所以,针对可以主动推送或自动提交的搜索引擎,还是以主动推送为主,sitemap
为辅。