Я пытаюсь создать простой веб-искатель с использованием PHP, который способен обходить домены .edu, при условии семенных URL-адресов родителя.
Я использовал простой html dom для реализации искателя, а часть основной логики реализована мной.
Я отправляю код ниже и попытаюсь объяснить проблемы.
private function initiateChildCrawler($parent_Url_Html) { global $CFG; static $foundLink; static $parentID; static $urlToCrawl_InstanceOfChildren; $forEachCount = 0; foreach($parent_Url_Html->getHTML()->find('a') as $foundLink) { $forEachCount++; if($forEachCount<500) { $foundLink->href = url_to_absolute($parent_Url_Html->getURL(), $foundLink->href); if($this->validateEduDomain($foundLink->href)) { //Implement else condition later on $parentID = $this->loadSaveInstance->parentExists_In_URL_DB_CRAWL($this->returnParentDomain($foundLink->href)); if($parentID != FALSE) { if($this->loadSaveInstance->checkUrlDuplication_In_URL_DB_CRAWL($foundLink->href) == FALSE) { $urlToCrawl_InstanceOfChildren = new urlToCrawl($foundLink->href); if($urlToCrawl_InstanceOfChildren->getSimpleDomSource($CFG->finalContext)!= FALSE) { $this->loadSaveInstance->url_db_html($urlToCrawl_InstanceOfChildren->getURL(), $urlToCrawl_InstanceOfChildren->getHTML()); $this->loadSaveInstance->saveCrawled_To_URL_DB_CRAWL(NULL, $foundLink->href, "crawled", $parentID); /*if($recursiveCount<1) { $this->initiateChildCrawler($urlToCrawl_InstanceOfChildren); }*/ } } } } } } }
Теперь, когда вы можете видеть, что initiateChildCrawler вызывается функцией initiateParentCrawler, которая передает родительскую ссылку дочернему искателю. Пример родительской ссылки: www.berkeley.edu, для которой искатель найдет все ссылки на главной странице и вернет все содержимое html. Это происходит до тех пор, пока семя не исчерпается.
например: 1-harvard.edu – >>>>> найдет все ссылки и вернет их содержимое html (путем вызова childCrawler). Переход к следующему родительскому элементу в parentCrawler. 2-berkeley.edu – >>>>> Вы найдете все ссылки и вернете свой html-контент (путем вызова childCrawler).
Другие функции самоочевидны.
Теперь проблема: после того, как childCrawler завершит цикл foreach для каждой ссылки, функция не сможет выйти из строя. Если я запускаю скрипт из CLI, CLI падает. При запуске скрипта в браузере завершается сценарий.
Но если я установил предел обхода дочерних ссылок на 10 или что-то меньшее (изменив переменную $ forEachCount), искатель начнет нормально работать.
Пожалуйста, помогите мне в этом.
Сообщение от CLI:
Подпись задачи: Проблема Имя события: APPCRASH Имя приложения: php-cgi.exe Версия приложения: 5.3.8.0 Временная метка приложения: 4e537939 Имя модуля неисправности: модуль ошибки php5ts.dll Версия: 5.3.8.0 Модуль сбоя Временная метка: 4e537a04 Код исключения: c0000005 Исключение Смещение: 0000c793 Версия ОС: 6.1.7601.2.1.0.256.48 Locale ID: 1033 Дополнительная информация 1: 0a9e Дополнительная информация 2: 0a9e372d3b4ad19135b953a78882e789 Дополнительная информация 3: 0a9e Дополнительная информация 4: 0a9e372d3b4ad19135b953a78882e789
Пример плоской петли:
Это будет выполняться до тех пор, пока все URL-адреса из стека не будут обработаны, поэтому вы добавите (как уже есть для foreach
) счетчик, чтобы предотвратить слишком длительное выполнение:
$URLStack = (array) $parent_Url_Html->getHTML()->find('a'); $URLProcessedCount = 0; while ($URLProcessedCount++ < 500) # this can run endless, so this saves us from processing too many URLs { $url = array_shift($URLStack); if (!$url) break; # exit if the stack is empty # process URL # for each new URL: $URLStack[] = $newURL; }
Вы можете сделать его еще более интеллектуальным, не добавляя URL-адреса в стек, который уже существует в нем, однако тогда вам нужно только вставить абсолютные URL-адреса в стек. Однако я настоятельно рекомендую вам сделать это, потому что нет необходимости обрабатывать страницу, которую вы уже получили (например, каждая страница содержит ссылку на домашнюю страницу). Если вы хотите сделать это, просто увеличивайте $URLProcessedCount
внутри цикла, чтобы сохранить предыдущие записи:
while ($URLProcessedCount < 500) # this can run endless, so this saves us from processing too many URLs { $url = $URLStack[$URLProcessedCount++];
Кроме того, я предлагаю вам использовать расширение PHP DOMDocument
вместо простого dom, поскольку это гораздо более универсальный инструмент.