Intereting Posts
Загружать альтернативный контент страницы в div onload Нужна помощь с SQL для ранжирования результатов поиска Не удалось установить соединение Swift_TransportException с узлом smtp.gmail.com Как проверить, является ли запрос AJAX-запросом с PHP Доступ к основному изображению страницы wikipedia по API yii2: Обновить значения в двух таблицах с помощью действия одного контроллера? Бесконечный плагин jquery прокрутки в кодеригенере Почему 65.6 * 100% 10 равно 9, вместо 0 в PHP? PHP PDO Fetch не работает? file_get_contents («php: // input») или $ HTTP_RAW_POST_DATA, какой из них лучше получить тело запроса JSON? CakeResque – Resque не найден в … app / Plugin / CakeResque / Lib / CakeResque.php в строке 82 Командная строка PHP mysql_connect () Ошибка Переменная конкатенированная строка запроса mysql отлично работает в phpMyAdmin, но не PHP в скрипте отображать данные из базы данных в таблицу html Регулярное выражение PHP: разделение на неэкранированный разделитель

Какой самый быстрый способ очистить много страниц в php?

У меня есть агрегатор данных, который опирается на очистку нескольких сайтов и индексирование их информации таким образом, который доступен для поиска пользователю.

Мне нужно ежедневно очищать огромное количество страниц, и я столкнулся с проблемами, используя простые запросы на завивки, которые довольно медленны, когда они выполняются в быстрой последовательности в течение длительного времени (скребок работает 24/7 в основном).

Выполнение запроса с несколькими завитушками в простом цикле while выполняется довольно медленно. Я ускорил его, выполнив отдельные запросы на завивки в фоновом режиме, который работает быстрее, но рано или поздно медленные запросы начинают накапливаться, что приводит к сбою сервера.

Существуют ли более эффективные способы очистки данных? возможно, кривая командной строки?

С большим количеством страниц вам понадобится какой-то многопоточный подход, потому что вы будете тратить большую часть своего времени на сетевой ввод-вывод.

В прошлый раз, когда я играл с потоками PHP, это было не так уж и много, но, возможно, это было изменено. Если вам нужно придерживаться PHP, это означает, что вы будете вынуждены перейти к многопроцессорному подходу: разделите свою рабочую нагрузку на N рабочих единиц и запустите N экземпляров вашего сценария, каждый из которых получит 1 рабочую единицу.

Языки, которые обеспечивают надежную и эффективную реализацию потоков, являются еще одним вариантом. У меня были хорошие впечатления от потоков в ruby ​​и C, и кажется, что потоки Java также очень зрелые и надежные.

Кто знает – возможно, потоки PHP улучшились с тех пор, как я играл с ними (~ 4 года назад) и стоит посмотреть.

По моему опыту выполнение запроса curl_multi с фиксированным количеством потоков является самым быстрым способом, вы можете поделиться используемым кодом, чтобы мы могли предложить некоторые улучшения? Этот ответ имеет довольно приличную реализацию curl_multi с многопоточным подходом, вот воспроизводимый код:

// -- create all the individual cURL handles and set their options $curl_handles = array(); foreach ($urls as $url) { $curl_handles[$url] = curl_init(); curl_setopt($curl_handles[$url], CURLOPT_URL, $url); // set other curl options here } // -- start going through the cURL handles and running them $curl_multi_handle = curl_multi_init(); $i = 0; // count where we are in the list so we can break up the runs into smaller blocks $block = array(); // to accumulate the curl_handles for each group we'll run simultaneously foreach ($curl_handles as $a_curl_handle) { $i++; // increment the position-counter // add the handle to the curl_multi_handle and to our tracking "block" curl_multi_add_handle($curl_multi_handle, $a_curl_handle); $block[] = $a_curl_handle; // -- check to see if we've got a "full block" to run or if we're at the end of out list of handles if (($i % BLOCK_SIZE == 0) or ($i == count($curl_handles))) { // -- run the block $running = NULL; do { // track the previous loop's number of handles still running so we can tell if it changes $running_before = $running; // run the block or check on the running block and get the number of sites still running in $running curl_multi_exec($curl_multi_handle, $running); // if the number of sites still running changed, print out a message with the number of sites that are still running. if ($running != $running_before) { echo("Waiting for $running sites to finish...\n"); } } while ($running > 0); // -- once the number still running is 0, curl_multi_ is done, so check the results foreach ($block as $handle) { // HTTP response code $code = curl_getinfo($handle, CURLINFO_HTTP_CODE); // cURL error number $curl_errno = curl_errno($handle); // cURL error message $curl_error = curl_error($handle); // output if there was an error if ($curl_error) { echo(" *** cURL error: ($curl_errno) $curl_error\n"); } // remove the (used) handle from the curl_multi_handle curl_multi_remove_handle($curl_multi_handle, $handle); } // reset the block to empty, since we've run its curl_handles $block = array(); } } // close the curl_multi_handle once we're done curl_multi_close($curl_multi_handle); 

Хитрость заключается в том, чтобы не загружать слишком много URL одновременно, если вы это сделаете, весь процесс будет зависать, пока не будут выполнены более медленные запросы. Я предлагаю использовать BLOCK_SIZE 8 или более, если у вас есть пропускная способность.

Если вы хотите запускать одиночные запросы на завивки, вы можете запускать фоновые процессы под Linux в PHP, например:

 proc_close ( proc_open ("php -q yourscript.php parameter1 parameter2 & 2> /dev/null 1> /dev/null", array(), $dummy )); 

Вы можете использовать параметры, чтобы дать вашему скрипту php некоторую информацию о том, какой url использовать, например LIMIT в sql.

Вы можете отслеживать текущие процессы, сохраняя их PID где-нибудь, чтобы поддерживать нужное количество процессов, запущенных одновременно, или убить процессы, которые не были завершены вовремя.