1

我现在有一个包含大约 300k 页的 Wordpress 站点,以及一个内存为 1GB 的服务器。不幸的是,所有的站点地图生成插件都无法处理它。我尝试了 3 种不同的使用 PHP 写入 XML 的方法(XMLWriter、SimpleXMLElement 和 DOMDocument),它们最终都达到了大约 30k 页(xml 节点)。

你认为我能做些什么来完成这项工作?最坏的情况是,我考虑过设置多个 cron 作业,每天每十分钟运行一次,并继续打开/附加到文件,然后分块添加,但这显然不是最佳解决方案。我发现了一些声称能够在我的循环期间清除内存的片段,但它也没有起到作用。这是该片段的示例:

$xml = '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">';
for ($i = 0 ; $i< 20; $i++) {
  $query = mysql_query(sprintf("SELECT ID, post_date FROM wp_posts WHERE post_status='publish' LIMIT %s,%s", $i*10000, 10000));
  while ($row = mysql_fetch_array($query)) {
    $xml .= '<url>';
    $xml .= '<loc>'.get_permalink($row['ID']).'</loc>';
    $xml .= '<lastmod>'.$row['post_date'].'</lastmod>';
    $xml .= '<changefreq>weekly</changefreq>';
    $xml .= '<priority>0.6</priority>';
    $xml .= '</url>';
  }
}
$xml .= '</urlset>';

$sxe = new SimpleXMLElement($xml);
$sxe->asXML("sitemap.xml");
4

1 回答 1

3

为什么要一次抓取所有记录?

尝试每个请求获取 10000 行。并在每次迭代后清理内存。

如果您在 cli 模式下运行旧版本的 php,则不会释放内存,因此您可以尝试 fork http://php.net/manual/en/function.pcntl-fork.php

怎么做:

  1. 无需使用任何 xml 库,sprintf就可以了。
  2. 将其包装成 for ($i = 0, $i < 5, $i++) {}
  3. 查询看起来像LIMIT ($i*10000) 10000

代码示例:

for ($i = 0 ; $i< 5 $i++) {
    ...
    $sth = $dbh->prepare('SELECT * FROM table_name LIMIT ? ?');
    $sth->execute(array($i*10000, 10000));
    ...
}

另一个代码示例:

    <?php
    $fileHandle = fopen("sitemap.xml", "w");

    fwrite($fileHandle,
        '<?xml version="1.0" encoding="UTF-8"?>' . 
        '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"' .
        ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' .
        ' xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9' .
        ' http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">'
    );

    for ($i = 0 ; $i< 20; $i++) {
        $query = mysql_query(sprintf("SELECT ID, post_date FROM wp_posts WHERE post_status='publish' LIMIT %s,%s", $i*10000, 10000));
        $xml = '';
        while ($row = mysql_fetch_array($query)) {
            $xml .= '<url>'.
                '<loc>'.get_permalink($row['ID']).'</loc>' .
                '<lastmod>'.$row['post_date'].'</lastmod>' .
                '<changefreq>weekly</changefreq>' .
                '<priority>0.6</priority>' .
                '</url>';
        }

        fwrite($fileHandle, $xml);
    }
    fwrite($fileHandle, '</urlset>');

    fclose($fileHandle);

    echo PHP_EOL . 'memory used: '. memory_get_peak_usage() . PHP_EOL;
于 2012-11-23T21:53:14.213 回答