保存站点地图 XML 文件,每个文件限制为 1000 个 URL


Save Sitemap XML Files Limit by 1000 URLs per each File

如何保存多个站点地图文件,每个文件受 1000 个 URL 的限制,例如 sitemap1.xml、sitemap2.xml

基本上我想通过put_file_content限制每个文件的foreach

我的代码是:

$sitemap = "<?xml version='"1.0'" encoding='"UTF-8'"?>
    <urlset xmlns='"http://www.sitemaps.org/schemas/sitemap/0.9'">
    <url>
    <loc>". Yii::app() -> getBaseUrl(true) ."</loc>
    <priority>1</priority>
    </url>
";
foreach($websites as $website) {
    $sitemap .= "<url>
        <loc>".$website['domain']."</loc>
        <priority>0.5</priority>
        </url>
    ";
}
$sitemap .= "</urlset>";
file_put_contents("sitemap.xml", $sitemap, LOCK_EX);

让我们快速创建该应用程序:

  1. 创建一些模板 XML,以便将网站添加到其中。
  2. NoRewindIteratorLimitIterator的帮助下将$websites分块

让我们从第二点开始,创建伪造URL和XML的过程,看看这是否容易连接:

$limit = 3;
$urls = new ArrayIterator(range(0, 9)); // 10 Fake URLs
$urls->rewind();
$it = new NoRewindIterator($urls);

首先,我们为每个文件设置一个限制(这里是三个以保持较低的测试),然后我们为 URL 设置数据源。这里有 10 个虚假 URL,只是从 0 到 9 的数字。

这些 URL 被倒带,

因为它们随后被包装到一个NoRewindIterator并且那个永远不会倒带,但我们想倒带数据源一次(这不是所有迭代器所必需的,但对于相当多的迭代器,所以我们这样做是正确的)。

倒带操作被NoRewindIterator阻止,以便我们可以继续获得 X 块的大小为 $limit .这正是现在所做的:

$fileCounter = 0;
while ($it->valid()) {    
    $fileCounter++;
    printf("File %d:'n", $fileCounter);
    $websites = new LimitIterator($it, 0, $limit);
    foreach($websites as $website) {
        printf(" * Website: %s'n", $website);
    }
}

只要$it有效(阅读:只要有要输出的 URL),就会创建一个新文件(从一个文件开始),然后通过 LimitIterator 对三个网站进行搜索。完成该迭代后,将继续执行,直到使用完所有网站 URL。输出如下:

File 1:
 * Website: 0
 * Website: 1
 * Website: 2
File 2:
 * Website: 3
 * Website: 4
 * Website: 5
File 3:
 * Website: 6
 * Website: 7
 * Website: 8
File 4:
 * Website: 9

到目前为止,这显示了如何进行分块(或者有时也称为分页)。如示例所示,仅缺少有关创建 XML 文档的部分。

对于创建XML文档,您可以连接一个字符串,但是,我们不这样做。我们使用现有的库,可以很好地完成这一切。该库称为 DOMDocument,下面是如何在 urlset 中创建具有两个示例位置的站点地图文件的示例:

$doc = new DOMDocument();
$doc->formatOutput = TRUE;
$nsUri    = 'http://www.sitemaps.org/schemas/sitemap/0.9';
$urlset = $doc->appendChild($doc->createElementNS($nsUri, 'urlset'));
$url = $doc->createElementNS($nsUri, 'url');
$location = $url->appendChild($doc->createElementNS($nsUri, 'loc', 'BASEURL'));
$priority = $url->appendChild($doc->createElementNS($nsUri, 'priority', '1'));
$urlset->appendChild(clone $url);
$priority->nodeValue = '0.5';
$location->nodeValue = 'TEST';
$urlset->appendChild(clone $url);
echo $doc->saveXML();

此代码示例演示如何创建文档,然后如何向其添加具有正确命名空间的元素。它还演示了如何创建可以通过克隆轻松修改和添加的样板<url>元素。

此示例的输出为:

<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>BASEURL</loc>
    <priority>1</priority>
  </url>
  <url>
    <loc>TEST</loc>
    <priority>0.5</priority>
  </url>
</urlset>

所以现在所有一般问题都解决了。所需要的只是将这两者联网并存储到磁盘上。为了这个例子,我省去了后面的部分(你只是将文件名作为参数传递到saveXML)并输出XML:

<?php
/**
 * Save Sitemap XML Files Limit by 1000 URLs per each File
 *
 * @link https://stackoverflow.com/q/19750485/367456
 */
$limit = 3;
$urls = new ArrayIterator(range(0, 9)); // 10 Fake URLs
$urls->rewind();
$it = new NoRewindIterator($urls);
$fileCounter = 0;
$baseDoc               = new DOMDocument();
$baseDoc->formatOutput = TRUE;
$nsUri = 'http://www.sitemaps.org/schemas/sitemap/0.9';
while ($it->valid()) {
    $fileCounter++;
    $doc = clone $baseDoc;
    $urlset = $doc->appendChild($doc->createElementNS($nsUri, 'urlset'));
    $url    = $doc->createElementNS($nsUri, 'url');
    $location = $url->appendChild($doc->createElementNS($nsUri, 'loc', 'BASEURL'));
    $priority = $url->appendChild($doc->createElementNS($nsUri, 'priority', '1'));
    $urlset->appendChild(clone $url);
    $priority->nodeValue = '0.5';
    printf("File %d:'n", $fileCounter);
    $websites = new LimitIterator($it, 0, $limit);
    foreach ($websites as $website) {
        $location->nodeValue = $website;
        $urlset->appendChild(clone $url);
    }
    echo $doc->saveXML();
}

然后,输出是XML而不是纯文本:

File 1:
<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>BASEURL</loc>
    <priority>1</priority>
  </url>
  <url>
    <loc>0</loc>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>1</loc>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>2</loc>
    <priority>0.5</priority>
  </url>
</urlset>
File 2:
<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>BASEURL</loc>
    <priority>1</priority>
  </url>
  <url>
    <loc>3</loc>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>4</loc>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>5</loc>
    <priority>0.5</priority>
  </url>
</urlset>
File 3:
<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>BASEURL</loc>
    <priority>1</priority>
  </url>
  <url>
    <loc>6</loc>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>7</loc>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>8</loc>
    <priority>0.5</priority>
  </url>
</urlset>
File 4:
<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>BASEURL</loc>
    <priority>1</priority>
  </url>
  <url>
    <loc>9</loc>
    <priority>0.5</priority>
  </url>
</urlset>

因此,现在剩下要做的就是在一开始就提供原始数据源作为迭代器,将 URL 的数量(限制)增加到您自己的值,并为每个文件添加正确的基本 URL(如果您确实需要的话)。

就XML站点地图而言,您还可以创建一个链接其他文件的文件。与以下限制相比,IIRC的限制要高一些:多个站点地图:机器人中的条目.txt?

我希望这可以帮助您以既定的方式实现您正在寻找的东西。

你可以尝试一个for循环(for($x = 0;$x <1000;$x++){$websites[$x] })或者你可以用外部变量退出foreach循环,如下所示:

$i = 1;
foreach ($websites as $website)
{
if ($i === 1000) break;
$i++;
#do your thing
}