Контроль памяти PHP

D
На сайте с 28.06.2008
Offline
1104
436

Написал парсер, ничего сложного 

В начале подключение к базе

$conn = new PDO("mysql:host=localhost;dbname=" . $database . ";charset=UTF8", $user, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Далее в цикле for хожу по страницам пагинации, собираю данные и пишу их в базу.

С помощью кода пытался посмотреть сколько тратиться памяти

        //контролируем память
        $memory = memory_get_usage() - $memory;
        $m = 0;
        while (floor($memory / 1024) > 0) {
            $m++;
            $memory /= 1024;
        }
        $name = array('байт', 'КБ', 'МБ');
        var_dump('Контроль памяти, страница '.$pageNum.', сейчас используется - '.round($memory, 2) . ' ' . $name[$m]);

показывает смешные цифры - 8-9 Мб.

Но контроль на втором экране Putty через htop показывает что скрипт плавно но верно сжирает всю память и потом крашится по аут оф мемори.

Да, объектов там много и цикл длинный, на 30-50 итераций, в каждой итерации 25 объектов (ссылок) по которым тоже нужно сходить и достать там инфу.

Скрипт может работать 30-50 минут.

Так как в скрипте по сути никакой логики, нашли объект по классу, записали в базу и т.д. у меня мысль только одна - может нужно закрывать соединение PDO и снова его открывать когда нужно?

На ВПС 2 гига оперативки, в момент начала работы свободно 1.85 Гб. 

В скрипте прописано

ini_set("memory_limit", "1500M");
set_time_limit(0);

Еще идея - может нужно закрывать curl внутри функции? Я из цикла через курл страницы дергаю, курл в функции, которую я вызываю из цикла, но курл внутри нее не закрывается.

W1
На сайте с 22.01.2021
Offline
304
#1
Посмотри на предмет лишних переменных. И удаляй их - unset().
Мой форум - https://webinfo.guru –Там я всегда на связи
LEOnidUKG
На сайте с 25.11.2006
Offline
1745
#2
webinfo #:
Посмотри на предмет лишних переменных. И удаляй их - unset().

Пока код не покажет, смысла обсуждать ничего нет.

Скорее всего там в какой-нибудь массив бесконечно забиваются данные.

✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/ ✅ Настройка и оптимизация серверов https://getmanyspeed.ru/
D
На сайте с 28.06.2008
Offline
1104
#3

Прошу не пинайтесь за goto ибо букинг иногда выдает как будтно пустую страницу. ХЗ почему так, но если вернуться в цикле вверх и снова ее загрузить, то все норм, поэтому goto....

//если результатов более 25, значит есть пагинации, начинаем ходить по ней
if ($number > 25) {
    preg_match('~<button(.*)">(.*)</button></li>\n</ol></div>~mU', $body, $matchBody);
    $pageNumber = (int)$matchBody[2];
    $pageNum = 25;
    for ($i = 2; $i <= $pageNumber; $i++) {
        bachFor:
        sleep(2);
        $urlNext = $url . "&offset=$pageNum";
        $pageNext = getPageByUrl($urlNext, $refer);
        $pq = phpQuery::newDocument($pageNext);
        $h3_a = $pq->find("h3")->find("a");
        if (!empty($h3_a)) {
            foreach ($h3_a as $item) {
                back2:
                sleep(2);
                $pq = pq($item);
                //ссылка на отель
                $href = $pq->attr('href');
                //заходим в каждый конкретный отель
                $pageHotel = getPageByUrl($href, $url);
                $href = preg_replace('~\.html(.*)~m', '\.html', $href);
                $pqHotel = phpQuery::newDocument('<meta charset="utf-8">' . $pageHotel);
                
                $name = $pqHotel->find(".hp__hotel-name")->text();
                $span = $pqHotel->find(".hp__hotel-name")->find("span")->text();
                $name = str_replace($span, '', $name);
                //название отеля
                $name = addslashes(trim(str_replace("\n", '', $name)));
                $name = str_replace(array('Апартаменты/квартираНовинка на Booking.com', 'ОтельНовинка на Booking.com', 'Дом для отпускаНовинка на Booking.com', 'ВиллаНовинка на Booking.com'), '', $name);
                var_dump($name);

                if (!empty($name)) {
                    //фото
                    $html = $pqHotel->find('html')->html();
                    preg_match_all("~large_url: '(.*)'~m", $html, $matchHtml);
                    //первое фото - $matchHtml[1][0] и т.д.

                    //Адрес отеля
                    $address = addslashes(trim($pqHotel->find('.address_clean')->find('span:eq(1)')->text()));
                    //город отеля
                    preg_match("~city_name: '(.*)'~m", $html, $matchCity);
                    $city = addslashes($matchCity[1]);
                    //улица
                    preg_match('~"addressLocality" : "(.*)"~m', $html, $matchAddressLocality);
                    $addressLocality = addslashes($matchAddressLocality[1]);
                    //Координаты
                    preg_match('~data-atlas-latlng="(.*)"~mU', $html, $matchGeo);
                    $geo = $matchGeo[1];
                    //тип жилья
                    preg_match("~atnm: '(.*)',~m", $html, $matchKind);
                    $kind = $matchKind[1];
                    //описание
                    $description = addslashes($pqHotel->find("#property_description_content")->text());
                    $description = preg_replace('~Вы можете получить Genius(.*)войдите в аккаунт.\n~mU', '', $description);
                    $description = str_replace("\n", ' ', $description);
                    //рейтинг
                    $rating = $pqHotel->find("#js--hp-gallery-scorecard")->attr('data-review-score');
                    //Самые популярные удобства и услуги
                    $facilitiesArr = [];
                    $facilities = $pqHotel->find(".hp_desc_important_facilities:eq(0)")->find('div');
                    foreach ($facilities as $facility) {
                        $pqFacility = pq($facility);
                        preg_match('~</svg>(.*)$~ms', $pqFacility->html(), $matchDiv);
                        if (!empty($matchDiv[1])) {
                            $option = trim($matchDiv[1]);
                            $option = str_replace("\n", ' ', strip_tags($option));
                            array_push($facilitiesArr, $option);
                        }
                    }
                    $options = implode('||', $facilitiesArr);
                    //Кровати для детей
                    $child = $pqHotel->find(".c-child-policies")->text();
                    $child = str_replace("\n", ' ', $child);
                    $child = str_replace("Правила размещения детей", 'Правила размещения детей.', $child);
                    $child = str_replace(".", '. ', $child);
                    $child = addslashes(str_replace("  ", ' ', $child));
                    //Возрастное ограничение
                    $age_restriction = addslashes($pqHotel->find("#age_restriction_policy")->find("p:eq(1)")->text());
                    //Домашние животные
                    preg_match("~<span>Домашние животные</span>(.*)<p>(.*)</p>~msU", $html, $matchHouse);
                    $house_rule = addslashes(trim($matchHouse[2]));
                    
                    $sqlList = $conn->query("SELECT id FROM `booking` WHERE `Название` = '{$name}' AND `Координаты` = '{$geo}'");
                    $resultList = $sqlList->fetchAll(PDO::FETCH_ASSOC);

                    if (empty($resultList)) {
                        $sql = ("INSERT INTO `booking` (`id`, `url`, `Название`, `Адрес`, `Город`, `Улица`, `Координаты`,
                       `Фото1`, `Фото2`, `Фото3`, `Фото4`, `Фото5`, `Фото6`, `Фото7`, `Фото8`, `Фото9`, `Фото10`, `Фото11`, `Фото12`,
                       `Тип`, `Описание`, `Рейтинг`, `Удобства`, `Кровати для детей`, `Возрастное ограничение`, `Домашние животные`)
                       VALUES (NULL, '{$href}', '{$name}', '{$address}', '{$city}', '{$addressLocality}', '{$geo}',
                               '{$matchHtml[1][0]}', '{$matchHtml[1][1]}', '{$matchHtml[1][2]}', '{$matchHtml[1][3]}', '{$matchHtml[1][4]}', '{$matchHtml[1][5]}', '{$matchHtml[1][6]}', '{$matchHtml[1][7]}', '{$matchHtml[1][8]}', '{$matchHtml[1][9]}', '{$matchHtml[1][10]}', '{$matchHtml[1][11]}',
                               '{$kind}', '{$description}', '{$rating}', '{$options}', '{$child}', '{$age_restriction}', '{$house_rule}');");
                        $conn->query($sql);
                    }
                    unset($pq);
                    unset($html);
                    unset($address);
                    unset($city);
                    unset($addressLocality);
                    unset($geo);
                    unset($kind);
                    unset($description);
                    unset($rating);
                    unset($facilities);
                    unset($facilitiesArr);
                    unset($options);
                    unset($child);
                    unset($age_restriction);
                    unset($house_rule);
                    unset($resultList);
                    unset($matchHtml);
                } else {
                    var_dump('пустое имя, возвращаемся в цикле и пробуем снова');
                    goto back2;
                }
            }
        } else {
            var_dump('возврат ' . $pageNum);
            goto bachFor;
        }
        $pageNum = $pageNum + 25;
        var_dump('PAGINATION---' . $i.', pageNum - '.$pageNum);
    }
}
LEOnidUKG
На сайте с 25.11.2006
Offline
1745
#4
Прошу не пинайтесь за goto ибо букинг иногда выдает как будтно пустую страницу.

Что такое функции разве не изучал?

Попробуй, может быть и память придёт в норму.

D
На сайте с 28.06.2008
Offline
1104
#5

Виноват ПХП Квери, нужно использовать

phpQuery::unloadDocuments(); //очистка документа
    gc_collect_cycles(); // принудительный вызов встроенного сборщика мусора PHP

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий