Laravel Sitemap 生成器 - 生成站点地图
spatie/laravel-sitemap 是一个 Laravel 站点的 Sitemap 生成器。可以在无需手动添加 URL 的情况下,爬取整个站点生成站点地图。
use Spatie\Sitemap\SitemapGenerator;
SitemapGenerator::create('https://example.com')->writeToFile($path);
你也可以手动生成站点地图(sitemap):
use Carbon\Carbon;
use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;
Sitemap::create()
->add(Url::create('/home')
->setLastModificationDate(Carbon::yesterday())
->setChangeFrequency(Url::CHANGE_FREQUENCY_YEARLY)
->setPriority(0.1))
->add(...)
->writeToFile($path);
或者你也可以生成 Sitemap 然后再添加链接:
SitemapGenerator::create('https://example.com')
->getSitemap()
->add(Url::create('/extra-page')
->setLastModificationDate(Carbon::yesterday())
->setChangeFrequency(Url::CHANGE_FREQUENCY_YEARLY)
->setPriority(0.1))
->add(...)
->writeToFile($path);
你也可以控制 Sitemap 的最大深度:
SitemapGenerator::create('https://example.com')
->configureCrawler(function (Crawler $crawler) {
$crawler->setMaximumDepth(3);
})
->writeToFile($path);
该生成器在每个页面中拥有[执行 JavaScript 的能力],因此由 JavaScript 注入到 DOM 的链接也可以爬取。
你也可以将 sitemap 写入到可用的文件系统磁盘。
SitemapGenerator::create('https://example.com')->getSitemap()->writeToDisk('public', 'sitemap.xml');
你也可用通过实现 \Spatie\Sitemap\Contracts\Sitemapable
接口,添加模型。
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
class Post extends Model implements Sitemapable
{
public function toSitemapTag(): Url | string | array
{
return route('blog.post.show', $this);
}
}
现在,你就可以添加单个 post 模型到 sitemap 或者甚至整个集合。
use Spatie\Sitemap\Sitemap;
Sitemap::create()
->add($post)
->add(Post::all());
这样可以很快就添加页面,而不必爬取所有页面。
安装
首先,通过 Composer 安装:
composer require spatie/laravel-sitemap
这个包会自己自动注册。
配置
你可以重写爬虫的默认选项。首先发布配置:
php artisan vendor:publish --provider="Spatie\Sitemap\SitemapServiceProvider" --tag=sitemap-config
这会复制默认的配置文件 config/sitemap.php
use GuzzleHttp\RequestOptions;
use Spatie\Sitemap\Crawler\Profile;
return [
/*
* These options will be passed to GuzzleHttp\Client when it is created.
* For in-depth information on all options see the Guzzle docs:
*
* http://docs.guzzlephp.org/en/stable/request-options.html
*/
'guzzle_options' => [
/*
* Whether or not cookies are used in a request.
*/
RequestOptions::COOKIES => true,
/*
* The number of seconds to wait while trying to connect to a server.
* Use 0 to wait indefinitely.
*/
RequestOptions::CONNECT_TIMEOUT => 10,
/*
* The timeout of the request in seconds. Use 0 to wait indefinitely.
*/
RequestOptions::TIMEOUT => 10,
/*
* Describes the redirect behavior of a request.
*/
RequestOptions::ALLOW_REDIRECTS => false,
],
/*
* The sitemap generator can execute JavaScript on each page so it will
* discover links that are generated by your JS scripts. This feature
* is powered by headless Chrome.
*/
'execute_javascript' => false,
/*
* The package will make an educated guess as to where Google Chrome is installed.
* You can also manually pass it's location here.
*/
'chrome_binary_path' => '',
/*
* The sitemap generator uses a CrawlProfile implementation to determine
* which urls should be crawled for the sitemap.
*/
'crawl_profile' => Profile::class,
];
用途
生成 sitemap
最简单的方法是爬取给定的域名,并用所有找到的链接生成 sitemap。
sitemap 的目标路径由 $path
指定:
SitemapGenerator::create('https://example.com')->writeToFile($path);
生成的 sitemap 类似于如此:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com</loc>
<lastmod>2016-01-01T00:00:00+00:00</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://example.com/page</loc>
<lastmod>2016-01-01T00:00:00+00:00</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
...
</urlset>
自定义 sitemap generator
定义自定义 Crawl Profile
你可以通过实现 Spatie\Crawler\CrawlProfiles\CrawlProfile
接口,并实现 shouldCrawl()
方法完全控制哪些 url/domain/subdomain 应该爬取,创建自定义爬虫:
use Spatie\Crawler\CrawlProfiles\CrawlProfile;
use Psr\Http\Message\UriInterface;
class CustomCrawlProfile extends CrawlProfile
{
public function shouldCrawl(UriInterface $url): bool
{
if ($url->getHost() !== 'localhost') {
return false;
}
return $url->getPath() === '/';
}
}
并在 config/sitemap.php
中注册 CustomCrawlProfile::class
:
return [
...
/*
* The sitemap generator uses a CrawlProfile implementation to determine
* which urls should be crawled for the sitemap.
*/
'crawl_profile' => CustomCrawlProfile::class,
];
修改属性
要修改页面的 lastmod
、changefreq
及 priority
:
use Carbon\Carbon;
use Spatie\Sitemap\SitemapGenerator;
use Spatie\Sitemap\Tags\Url;
SitemapGenerator::create('https://example.com')
->hasCrawled(function (Url $url) {
if ($url->segment(1) === 'contact') {
$url->setPriority(0.9)
->setLastModificationDate(Carbon::create('2016', '1', '1'));
}
return $url;
})
->writeToFile($sitemapPath);
省略部分链接
如果您不希望已爬取的链接出现在网站地图中,请不要将其返回到您传递 hasCrawled
的可调用项中。
use Spatie\Sitemap\SitemapGenerator;
use Spatie\Sitemap\Tags\Url;
SitemapGenerator::create('https://example.com')
->hasCrawled(function (Url $url) {
if ($url->segment(1) === 'contact') {
return;
}
return $url;
})
->writeToFile($sitemapPath);
防止爬虫爬取某些页面
您还可以通过将“ callable
传递给 shouldCrawl
来指示底层爬网程序不要对某些页面进行爬取。
注:`shouldCrawl` 只能与默认爬虫
Profile
或者实现shouldCrawlCallaback
方法的自定义 crawl profile 一起工作。
use Spatie\Sitemap\SitemapGenerator;
use Psr\Http\Message\UriInterface;
SitemapGenerator::create('https://example.com')
->shouldCrawl(function (UriInterface $url) {
// All pages will be crawled, except the contact page.
// Links present on the contact page won't be added to the
// sitemap unless they are present on a crawlable page.
return strpos($url->getPath(), '/contact') === false;
})
->writeToFile($sitemapPath);
配置爬虫
爬虫本身可以配置做许多不同的事情。
你可以使用 sitemap 生成器配置爬虫,比如:忽略 robot 检测,像这样:
SitemapGenerator::create('http://localhost:4020')
->configureCrawler(function (Crawler $crawler) {
$crawler->ignoreRobots();
})
->writeToFile($file);
限制页面爬取数量
调用 setMaximumCrawlCount
可以限制页面爬取数量
use Spatie\Sitemap\SitemapGenerator;
SitemapGenerator::create('https://example.com')
->setMaximumCrawlCount(500) // only the 500 first pages will be crawled
...
执行 Javascript
这个站点生成器可以在每个页面中执行 JavaScript,因此它将发现由JS脚本生成的链接。您可以通过将配置文件中的 execute_javascript
设置为true
来启用此功能。
在底层,它使用[无头 Chrome](https://github.com/spatie/browsershot) 执行 JavaScript。这里有一些如何在你的系统中安装的指示。
该软件包将对Chrome在您的系统上的安装位置进行有根据的猜测。您还可以手动将Chrome二进制文件的位置传递给 executeJavaScript()
。
手动添加链接
你也可以手动添加链接到 sitemap:
use Spatie\Sitemap\SitemapGenerator;
use Spatie\Sitemap\Tags\Url;
SitemapGenerator::create('https://example.com')
->getSitemap()
// here we add one extra link, but you can add as many as you'd like
->add(Url::create('/extra-page')->setPriority(0.5))
->writeToFile($sitemapPath);
添加备选方案到链接Adding alternates to links
多语言网站可能有多个相同页面的备用版本(每种语言一个)。根据前面的示例,添加备选方案可以按如下方式进行:
use Spatie\Sitemap\SitemapGenerator;
use Spatie\Sitemap\Tags\Url;
SitemapGenerator::create('https://example.com')
->getSitemap()
// here we add one extra link, but you can add as many as you'd like
->add(Url::create('/extra-page')->setPriority(0.5)->addAlternate('/extra-pagina', 'nl'))
->writeToFile($sitemapPath);
注意 addAlternate
函数需要一个 alternate URL,以及它所属语言。
将图片添加到链接
URL 也可以有图片。
use Spatie\Sitemap\Sitemap;
use Spatie\Sitemap\Tags\Url;
Sitemap::create()
// here we add an image to a URL
->add(Url::create('https://example.com')->addImage('https://example.com/images/home.jpg', 'Home page image'))
->writeToFile($sitemapPath);
手动创建 sitemap
你也可以完全手动创建 sitemap:
use Carbon\Carbon;
Sitemap::create()
->add('/page1')
->add('/page2')
->add(Url::create('/page3')->setLastModificationDate(Carbon::create('2016', '1', '1')))
->writeToFile($sitemapPath);
创建 sitemap index
你可以创建 sitemap 索引:
use Spatie\Sitemap\SitemapIndex;
SitemapIndex::create()
->add('/pages_sitemap.xml')
->add('/posts_sitemap.xml')
->writeToFile($sitemapIndexPath);
你可以传入一个 Spatie\Sitemap\Tags\Sitemap
对象,手动设置 lastModificationDate
属性。
use Spatie\Sitemap\SitemapIndex;
use Spatie\Sitemap\Tags\Sitemap;
SitemapIndex::create()
->add('/pages_sitemap.xml')
->add(Sitemap::create('/posts_sitemap.xml')
->setLastModificationDate(Carbon::yesterday()))
->writeToFile($sitemapIndexPath);
生成的站点地图索引像这样:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>http://www.example.com/pages_sitemap.xml</loc>
<lastmod>2016-01-01T00:00:00+00:00</lastmod>
</sitemap>
<sitemap>
<loc>http://www.example.com/posts_sitemap.xml</loc>
<lastmod>2015-12-31T00:00:00+00:00</lastmod>
</sitemap>
</sitemapindex>
使用后续站点地图创建站点地图索引
你可以调用 maxTagsPerSitemap
方法,取生成只包含给定数量 tag 的 sitemap
use Spatie\Sitemap\SitemapGenerator;
SitemapGenerator::create('https://example.com')
->maxTagsPerSitemap(20000)
->writeToFile(public_path('sitemap.xml'));
频繁生成 sitemap
你的网站可能会时不时更新。为了让 sitemap 映射这些更新,你可以定期运行这个生成器。最简单的方式是使用 Laravel 默认的任务调度工具。
你可以像这样创建一个 artisan 命令:
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Spatie\Sitemap\SitemapGenerator;
class GenerateSitemap extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $signature = 'sitemap:generate';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate the sitemap.';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// modify this to your own needs
SitemapGenerator::create(config('app.url'))
->writeToFile(public_path('sitemap.xml'));
}
}
```
That command should then be scheduled in the console kernel.
```php
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
...
$schedule->command('sitemap:generate')->daily();
...
}