Ошибки относительно Web Crawler в PHP - PullRequest
2 голосов
/ 31 декабря 2011

Я пытаюсь создать простой веб-сканер, использующий 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-содержимое.Это происходит до тех пор, пока исходные URL-адреса не будут исчерпаны.

, например: 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 Идентификатор локали: 1033 Дополнительная информация1: 0a9e Дополнительная информация 2: 0a9e372d3b4ad19135b953a78882e789 Дополнительная информация 3: 0a9e Дополнительная информация 4: 0a9e372d3b4ad19135b953a78882e789

1 Ответ

1 голос
/ 31 декабря 2011

Пример плоской петли:

  1. Вы запускаете цикл со стеком, который содержит все URL-адреса, которые вы хотите обработать первыми.
  2. Внутри цикла:
    1. Вы смещаете первый URL (вы получаете его, и он удален) из стека.
    2. Если вы найдете новые URL, вы добавляете их в конец стека ( push ).

Это будет выполняться до тех пор, пока не будут обработаны все 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, поскольку это гораздо более универсальный инструмент.

...