Не хватает памяти при парсинге страниц

Через цикл парсю страницы каталога (там свыше 1000 страниц). Нужно вытащить артикул, цену, фотки, характеристики. Начал только с артиклей. После 6 страниц память заканчивается и выбрасывает 500 ошибку.

$y=0; foreach ($allUrl as $url) {
        $y++;
        if ($y<7) {
         $html = file_get_html($url);
         if ($html->find('.product_detail_info_block__article')) {
          $title = $html->find('.product_detail_info_block__article',0)->find('span',1)->plaintext;
          echo $title.'<br>';                                      
               $html->clear();
                unset($html);
                $html = null;
            } 
        } else break; }

Увеличил FcgidConnectTimeout до 200. Не помогло. Сайт на FastCGI (Apache).

Как я понял увеличением памяти здесь ничего не сделаешь - нужно парсить по несколько страниц. А как технически это делается?

У меня задача - на сайте дилера обновлять товары в каталоге ( обновлять цены, характеристики если товар есть (сравнение по артикулу) и добавлять новый товар если товара нет). Доступа к базе данных сайта донора нет. XML для импорта товаров тоже нет. Поэтому решил писать парсер для сбора информации с фронтенда. И вперся в ограничение памяти. Как правильно выстроить парсинг?

Есть такая идея

  • В базе данных в строке товара добавляю колонки - время обновления (time_upd) и ссылку на товар донора (link)
  1. В цикл загружаю перебор ссылок на страницы донора (которые ранее получены из xml).
  2. По базе данных пробегаю столбец link и нахожу совпадение.
  3. Смотрю у совпавшего товара time_upd.
  4. Если стоит не сегодняшнее число, то обновляю его, в т.ч. time_upd меняю на текущий день.

В таком цикле обрабатывать не более 5 страниц. И тут опять вопрос. Это что вручную запускать скрипт, пока не обработает все 1000+ товаров?


UPD. Сделал решение в соответствии с идеей ниже. Для перезапуска скрипта использую curl.Ранее пробовал еще header (через некоторое время на фронтенде возникает ошибка - слишком много переадресаций, но скрипт все равно продолжает работать до некоторых пор - остановился на 665 странице). Переделал запуск скрипта через curl.

        include 'simple_html_dom.php';

$allUrl = parseXML("https://xn--63-vlch8au.xn--p1ai/sitemap-iblock-58.xml");
$len_arr = count($allUrl);

    
if($_GET['arr_count']) {
    $key = $_GET['arr_count'];
    parse($key,$len_arr,$allUrl);
} else {
    $key = 0;
    parse($key,$len_arr,$allUrl);
}   

//------------------------------------------------------------------------------//

//Парсим XML с ссылками страниц каталога    
function parseXML($xml_url) {
    $content = simplexml_load_file($xml_url);   // парсим список ссылок     
    if ($content !== false ) {
        $x=0;
        foreach ($content->url as $url) {
            $x++;
                $allUrl[] =$url->loc; // заносим в массив все ссылки        
        }
    } else {
        echo "<p>Проблема с парсингом xml страницы - донора ссылок. При отправке запроса на <b><a href=".$xml_url.">".$xml_url."</a></b> появляется ошибка. Проверьте существует ли страница.</p>";
    }
    return $allUrl;
}

//Парсим страницы каталога  
function parse($key,$len_arr,$allUrl) {     //Аргументы функции $key - ключ массива $allUrl. С него начинаем парсить страницы. $len_arr - размер массива $allUrl. $allUrl - массив с ссылками на каталог.
$y=0;
for ($key; $key<=$len_arr; $key++) {
    
    if ($y<=9) {
        $file = fopen('parser_file.txt', 'a');
        $html = file_get_html($allUrl[$key]);
        if ($html->find('.product_detail_info_block__article')) {
            $title = $html->find('.product_detail_info_block__article',0)->find('span',1)->plaintext;
            fwrite($file, $key.' '.$title.''. PHP_EOL);
            fclose($file);
            echo $title.'<br>';
            $html->__destruct();
            $html->clear();
            unset($html);
            $html = null;
            $y++;
        } 
    } else {
        $key = $key+1;              
    
        $url = 'https://skifpro.kz/parser.php?arr_count='.$key;

        $headers = []; // создаем заголовки

        $curl = curl_init(); // создаем экземпляр curl

        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_VERBOSE, 1); 
        curl_setopt($curl, CURLOPT_POST, false); // 
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_exec($curl);
        curl_close($curl);      
        exit;
    
    }
    }       
}

Ответы (1 шт):

Автор решения: Павел Кравчук

Cделайте пошаговую обработку данных, не отдавайте массив с тысячей URL, при обработке которых он гарантированно упадет. Если он успевает обработать только 5 страниц - отдайте ему 5 первых url, сохраните промежуточный результат работы (последний обработанный url), затем вызовите из самого скрипта при помощи curl его же, который начнет свою работу со следующих 5 url - и так далее.

→ Ссылка