Не хватает памяти при парсинге страниц
Через цикл парсю страницы каталога (там свыше 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)
- В цикл загружаю перебор ссылок на страницы донора (которые ранее получены из xml).
- По базе данных пробегаю столбец link и нахожу совпадение.
- Смотрю у совпавшего товара time_upd.
- Если стоит не сегодняшнее число, то обновляю его, в т.ч. 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 - и так далее.