2010-01-21 4 views
1

Я разрабатываю приложение, которое, проще говоря, основано на нишевой поисковой системе. Внутри приложения у меня есть функция crawl(), которая сканирует веб-сайт, а затем использует функцию collectData() для хранения правильных данных с сайта в таблице «продукты», как описано в этой функции. Посещенные страницы хранятся в базе данныхCakePHP Утечка памяти сканера CakePHP

Сканер работает очень хорошо, как описано, за исключением двух вещей: таймаута и памяти. Мне удалось исправить ошибку тайм-аута, но память остается. Я знаю, что просто увеличение memory_limit на самом деле не устраняет проблему.

Эта функция запускается при посещении «EXAMPLE.COM/products/crawl».

Является ли утечка памяти неизбежной с помощью сканера PHP Web? ИЛИ есть что-то, что я делаю неправильно/не делаю.

Заранее спасибо. (КОД НИЖЕ)

function crawl() { 

     $this->_crawl('http://www.example.com/','http://www.example.com'); 
    } 

    /*** 
    * 
    * This function finds all link in $start and collects 
    * data from them as well as recursively crawling them 
    * 
    * @ param $start, the webpage where the crawler starts 
    * 
    * @ param $domain, the domain in which to stay 
    * 
    ***/ 

    function _crawl($start, $domain) { 
     $dom = new DOMDocument(); 
     @$dom->loadHTMLFile($start); 

     $xpath = new DOMXPath($dom); 
     $hrefs = $xpath->evaluate("/html/body//a");//get all <a> elements 

     for ($i = 0; $i < $hrefs->length; $i++) { 

      $href = $hrefs->item($i); 
      $url = $href->getAttribute('href'); // get href value 
      if(!(strpos($url, 'http') !== false)) { //check for relative links 
       $url = $domain . '/' . $url; 
      } 

      if($this->Page->find('count', array('conditions' => array('Page.url' => $url))) < 1 && (strpos($url, $domain) !== false)) { // if this link has not already been crawled (exists in database) 

       $this->Page->create(); 
       $this->Page->set('url',$url); 
       $this->Page->set('indexed',date('Y-m-d H:i:s')); 
       $this->Page->save(); // add this url to database 

       $this->_collectData($url); //collect this links data 
       $this->_crawl($url, $domain); //crawl this link 
      } 
     } 
    } 

ответ

1

Вы создаете вверх в два раза больше запросов к базе данных, поскольку есть ссылки на странице, я бы сказал, что это, где ваша проблема. Попробуйте просто скопировать ссылки в массив, сделать один большой пакетный запрос, чтобы отфильтровать дубликаты и вставить новые записи с помощью saveAll().


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

+0

Благодарим Вас за отзыв. Какие-нибудь советы по реализации этого? Концепция относительно проста, но я не уверен в создании отдельного экземпляра. Могу ли я, например, вызвать EXAMPLE.COM/products/crawl из сценария для запуска отдельного экземпляра? – KTastrophy

+0

Нет, вам лучше работать с заданиями cron или демоном. На SO есть много потоков, чтобы вы начали: http://stackoverflow.com/search?q=php+queue+worker – deceze

Смежные вопросы