Wordpress cron作业,CSV文件导入大小

时间:2018-04-04 01:12:46

标签: php wordpress csv

所以我正在使用WP-Cron,这是我的php cron工作我正在运行的问题是文件大小我无法弄清楚如何处理文件大小,它相当于1gb的巨大数量。 https://data.medicare.gov/api/views/mj5m-pzi6/rows.csv这是此处的CSV文件。

       $args = array(
            'numberposts' => -1,
            'post_status' => 'any'
        );

        $ids = get_posts($args);

        foreach($ids as $id) {
            wp_delete_post($id->ID, true);
        }
        header("Content-type: text/csv");
        $csv = file_get_contents('https://data.medicare.gov/api/views/mj5m-pzi6/rows.csv');

        $lines = explode(PHP_EOL, $csv);
        $array = array();

        foreach ($lines as $line) {
        $array[] = str_getcsv($line);
        }
        for ($i=1; $i < count($array); $i++) {
        if($array[$i][0] == '') {
            $ad1 = 'Null';
        } else {
            $ad1 = $array[$i][0];
        }

        if($array[$i][1] == '') {
            $ad2 = 'Null';
        } else {
            $ad2 = $array[$i][1];
        }

        $content = "Address 1: ".$ad1." Address 2: ".$ad2."</br>";


        $post = array(
            'post_title' => $ad1,
            'post_content' => $content,
            'post_status' => 'publish',
            'post_author' => 1
        );
        wp_insert_post($post);
        }

1 个答案:

答案 0 :(得分:0)

这应该更有效率

我尝试重写这一点。原来只是不可爱,但我试图保持它在功能上等同。

$csv = file_get_contents();

$lines = explode(PHP_EOL, $csv);
$array = array();

foreach ($lines as $line) {
    $array[] = str_getcsv($line);
}
for ($i=1; $i < count($array); $i++) {
    if($array[$i][0] == '') {
        $ad1 = 'Null';
    } else {
        $ad1 = $array[$i][0];
    }

    if($array[$i][1] == '') {
        $ad2 = 'Null';
    } else {
        $ad2 = $array[$i][1];
    }

    $content = "Address 1: ".$ad1." Address 2: ".$ad2."</br>";


    $post = array(
        'post_title' => $ad1,
        'post_content' => $content,
        'post_status' => 'publish',
        'post_author' => 1
    );
    wp_insert_post($post);
}

但是没有任何数据可以查看,并且不知道脚本的顶部部分与这些有什么关系,这是我能做的最好的。还有一些嵌套级别,我只是拒绝使用。

$handle = fopen('https://data.medicare.gov/api/views/mj5m-pzi6/rows.csv', 'r');
while(!feof($handle)){
    $line = fgetcsv($handle);
    /*
      the original has this $array[$i][0], $array[$i][1] we don't have the 
      $i level so this is just the first/second columns

      {condition} ? true : false - these are ternary statements which are
      just a way of doing a shorthand if condition.
    */
    $ad1 = ($line[0] == '') ? 'Null' : $line[0];
    $ad2 = ($line[1] == '') ? 'Null' : $line[1];

    /*
      you might want to add this check in, continue will skip to the next
      iteration, the if checks if both ad1 and ad2 are 'Null` so these look
      to me to be empty rows, so just un-comment that to skip them
    */
    //if($ad1 == 'Null' && $ad2 == 'Null') continue;

    $content = "Address 1: ".$ad1." Address 2: ".$ad2."</br>";

    //short hand array syntax PHPv5.4+ 
    $post = [
        'post_title' => $ad1,
        'post_content' => $content,
        'post_status' => 'publish',
        'post_author' => 1
    ];
    wp_insert_post($post);
}

这不是什么大不了的事,因为它花了我10分钟。希望它适合你,我无法测试它。您可能会注意到它比原件短得多。

  

HyYa我就像一个代码忍者,他们半扒。

这里的关键是原始打开整个文件到内存中。然后它将它爆炸成一个庞大的数组,然后它迭代虽然它不是一次而是2x。然后它插入。

我的版本,分别拉出每一行,检查它,插入,从内存中转储它。这在内存管理方面显然要好得多。你不应该用这个版本耗尽内存。

那说你可能还会用完时间。你可以添加这样的东西。

while(!feof($handle)){
    set_time_limit(60); //1 minutes per iteration

当然,您可以设置set_time_limit(0);或无限时间。

然而,Apache的超时很可能会让你,因为我认为WP-Cron实际上并没有使用CRON。或者换句话说,不在命令行(CLI)上运行。但我喜欢根据迭代给它一个限制然后它不是无限的。基本上这表示只要这个迭代花费不到1分钟就不会超时。但正如我所说,我不认为这是一个“真正的”Cron工作。它更像是一个在wordpress中运行的调度程序,因此你仍然依赖于Apache服务器。

可能有一种方法可以将它绑定到一个真正的Cron Job中,但是现在我在漫无边际,而且此时并不重要(我不是一个很大的Wordpress用户)

最后几件事

<强> 1

这看起来像一个远程文件https://,如果先将其保存,然后通过它,可能会获得更好的性能。但我不担心,除非你有网络问题,因为那时你正在做双重职责。但是如果你在阅读它时遇到的问题比我建议的要快,那么使用类似stream_copy_to_stream之类的东西在不插入数据库的情况下更快地将其写入磁盘,然后在保存之后再次查看它,然后用{删除文件{1}}

unlink

这样你就可以在开始之前在本地拥有整个文件,但应该清楚为什么我说它是双重职责。

<强> 2

我不确定这与CSV部分有什么关系,似乎这是一个单独的交易。

 $remote = fopen('https://...', 'r');
 $local  = fopen('localfile.css', 'w+'); //write/read mode

 stream_copy_to_stream($remote, $local);

 fclose($remote);
 rewind($local); //rewind file pointer to start
 ...other code..

最好将脚本集中在一个任务上,这样可以使维护更容易。也许这是其中的一部分?我只是没有看到任何变量将它绑定到CSV部分,并且顶部缺少一些代码。所以我忽略了它并专注于CSV部分。

第3

只有在输出类似下载内容的内容时才需要此标头。这告诉浏览器它的内容是什么时间,如果你没有通过输出它给浏览器,那么它最多是不必要的,最坏的情况是如果你在发送标题后尝试做某些事情会导致错误。像重定向一样,但我不认为在这个用例中发生了这种情况。

    $args = array(
        'numberposts' => -1,
        'post_status' => 'any'
    );

    $ids = get_posts($args);

    foreach($ids as $id) {
        wp_delete_post($id->ID, true);
    }

<强>综述

不要采取我说的错误语气,人们倾向于和我一起做。在批评代码方面,我只是非常生硬。每个人都必须学习,我真的在我们读取可以达到10兆字节的CSV文件的地方工作。我们做过的最大的一行是1500万行,我们经常读取大约100万行的文件。

我们使用SPLFileObject作为我们的CSV阅读器的基础,它非常酷,但可能有点矫枉过正。无论如何,这可能是读取CSV的最有效方式,而不会让任何事情变得疯狂。

随意询问您是否对其工作方式有任何疑问。

更新

你应该用真正的CRON

来运行它

What is the Real CRON

这是一个高级主题,而wordpress并没有让它变得更容易。我可以就此发表另外一篇文章。但它从CLI命令行界面运行PHP,它绕过了在Apache下运行的一些限制(如timelimit)。

让WP以这种方式运行将是一个小技巧,但我把一些我用Google搜索的东西放在一起,其中一些来自个人知识。

在webroot之外运行wordpress(在public_html之外)从CLI,假设它位于名为 header("Content-type: text/csv"); 的文件夹中,该文件夹是webroot /home/website/cron

的兄弟
/home/website/public_html

希望有所帮助。