DoorWay.su
    Вход свободный
DoorWay.su
Главная > Spider bot на PHP

 

Spider bot на PHP

Мы начали один проект, для которого необходимо постоянно собирать информацию из сети в автоматическом режиме, причём в большом количестве. Написал spider. В его основу был положен Zend Framework и небольшой, в процессе переработанный, скрипт Qu для работы с MySQL, придуманный мной ещё при царе Горохе. К набору этих простых функций я привык и никак не смог с ними расстаться. Стиль кодирования и организации классов и файлов соответствует требованиям Zend Coding Style.

Консольное приложение

Паук не имеет необходимости в веб-интерфейсе и поэтому был написан в виде скрипта для консоли. PHP для выполнения консольных приложений подхватывает основной конфиг, но принудительно переопределяет некоторые директивы (например можно не заботиться о max_execution_time). Так же доступны STDIN, STDOUT, STDERR константы. Подробнее об этом можно почитать в соответствующем разделе документации.

В процессе выяснилось, что паук выполняет много разных задач, и для этого необходимы параметры запуска. Параметры нужно применять без использования «-» перед названием, иначе php примет его за свой и не передаст скрипту. Я выбрал простую схему: «имя=значение [имя=значение]». Ассоциативный массив параметров у меня формирует единственная глобальная функция options(), параметры извлекаются из также глобального массива $argv.

1
2
3 /**
4 * str 2 array & array 2 str (name=value name2=value2)
5 *
6 * @global array $argv
7 * @param array|null $options
8 * @return array|string options
9 */
10 function options(array $options = null)
11 {
12     if (is_array($options)) {
13     $str = '';
14     foreach($options as $k=>$v){
15       $str .= trim($k) . (trim($v)?'='.trim($v):'').' ';
16     }
17     return trim($str);
18    }
19    global $argv;
20    $args = $argv;
21    $options = array();
22    unset($args[0]);
23    foreach ($args as $arg) {
24     $a = explode('=', $arg, 2);
25     $value = @trim($a[1] ? $a[1] : '');
26     $value = is_numeric($value) ? (int)$value : $value;
27     $options[strtolower(trim($a[0]))] = $value;
28   }
29   ksort($options);
30   return $options;
31 }
32
33

Эта функция используется один раз и передаёт параметры в «фасад» приложения. Правда Facade недавно был переименован в Program, а теперь в Starter, это больше отражает характер его действий. В общем, рефакторинг идёт практически постоянно.

Неваляшка

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

Первая же задача по начальному сбору данных вскрыла все непредусмотренные узкие места. Паук падал по самым разным причинам. Упавшее приложение нужно как-то поднимать. Так как задач множество, поднимать нужно только то, что упало. Поэтому и был переписан Facade в Starter.

Класс Starter отслеживает какие задачи запускаются и не даёт выполнять одинаковые задачи параллельно, а само главное — имеет механизм проверки и восстановления упавших задач, я их называю программами, т. к. задачами уже называются классы, реализующие обновление и сбор расширенных данных.

В крон был добавлен запуск паука в режиме проверки на каждые пятнадцать минут. В процессе проверки, он ищет активные процессы запущенных программ и восстанавливает их в случае отсутствия. Для проверки процесса в *nix есть команда ps, в windows — qprocess. В свою очередь нужно запомнить свой процесс перед запуском программы используя функцию getmypid().

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

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

Версия PHP 5.2.8 под FreeBSD, для консольного приложения в режиме CGI занимает примерно 25−30 Мб, при аппетитах самого скрипта к памяти в 2−3 Мб.

Продолжение следует...

 

Сайт создан в 2008 г. © DoorWay.su | Создание сайта — Seoded.ru