Как мне сделать простой сканер в PHP? - PullRequest
65 голосов
/ 22 февраля 2010

У меня есть веб-страница с кучей ссылок. Я хочу написать скрипт, который бы сбрасывал все данные, содержащиеся в этих ссылках, в локальный файл.

Кто-нибудь делал это с PHP? В качестве ответа достаточно общих указаний и ошибок.

Ответы [ 15 ]

1 голос
/ 16 сентября 2015

Я использовал код @ hobodave с этим небольшим изменением, чтобы предотвратить повторное сканирование всех вариантов фрагментов одного и того же URL:

<?php
function crawl_page($url, $depth = 5)
{
  $parts = parse_url($url);
  if(array_key_exists('fragment', $parts)){
    unset($parts['fragment']);
    $url = http_build_url($parts);
  }

  static $seen = array();
  ...

Затем вы можете опустить строку $parts = parse_url($url); в цикле for.

0 голосов
/ 03 января 2019

Это старый вопрос. С тех пор произошло много хорошего. Вот мои два цента на эту тему:

  1. Для точного отслеживания посещенных страниц сначала необходимо нормализовать URI. Алгоритм нормализации включает в себя несколько шагов:

  2. Не только у тега <a> есть атрибут href, у тега <area> он тоже есть https://html.com/tags/area/. Если вы не хотите ничего пропустить, вы должны также удалить тег <area> .

  3. Отслеживание хода сканирования. Если веб-сайт маленький, это не проблема. Наоборот, это может быть очень неприятно, если вы сканируете половину сайта, и это не удалось. Рассмотрите возможность использования базы данных или файловой системы для хранения прогресса.

  4. Будьте добры к владельцам сайтов. Если вы когда-либо собираетесь использовать свой сканер за пределами своего веб-сайта, вы должны использовать задержки. Без задержек скрипт работает слишком быстро и может значительно замедлить работу некоторых небольших сайтов. С точки зрения системных администраторов, это похоже на DoS-атаку. Статическая задержка между запросами сделает свое дело.

Если вы не хотите с этим сталкиваться, попробуйте Crawlzone и сообщите мне свой отзыв. Также ознакомьтесь со статьей, которую я написал некоторое время назад https://www.codementor.io/zstate/this-is-how-i-crawl-n98s6myxm

0 голосов
/ 05 февраля 2018

Я создал небольшой класс, чтобы получать данные из предоставленной ссылки, а затем извлекать HTML-элементы на ваш выбор. Класс использует CURL и DOMDocument.

класс php:

class crawler {


   public static $timeout = 2;
   public static $agent   = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)';


   public static function http_request($url) {
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL,            $url);
      curl_setopt($ch, CURLOPT_USERAGENT,      self::$agent);
      curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, self::$timeout);
      curl_setopt($ch, CURLOPT_TIMEOUT,        self::$timeout);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
      $response = curl_exec($ch);
      curl_close($ch);
      return $response;
   }


   public static function strip_whitespace($data) {
      $data = preg_replace('/\s+/', ' ', $data);
      return trim($data);
   }


   public static function extract_elements($tag, $data) {
      $response = array();
      $dom      = new DOMDocument;
      @$dom->loadHTML($data);
      foreach ( $dom->getElementsByTagName($tag) as $index => $element ) {
         $response[$index]['text'] = self::strip_whitespace($element->nodeValue);
         foreach ( $element->attributes as $attribute ) {
            $response[$index]['attributes'][strtolower($attribute->nodeName)] = self::strip_whitespace($attribute->nodeValue);
         }
      }
      return $response;
   }


}

пример использования:

$data  = crawler::http_request('/1524765/kak-mne-sdelat-prostoi-skaner-v-php');
$links = crawler::extract_elements('a', $data);
if ( count($links) > 0 ) {
   file_put_contents('links.json', json_encode($links, JSON_PRETTY_PRINT));
}

пример ответа:

[
    {
        "text": "Stack Overflow",
        "attributes": {
            "href": "https:\/\/stackoverflow.com",
            "class": "-logo js-gps-track",
            "data-gps-track": "top_nav.click({is_current:false, location:2, destination:8})"
        }
    },
    {
        "text": "Questions",
        "attributes": {
            "id": "nav-questions",
            "href": "\/questions",
            "class": "-link js-gps-track",
            "data-gps-track": "top_nav.click({is_current:true, location:2, destination:1})"
        }
    },
    {
        "text": "Developer Jobs",
        "attributes": {
            "id": "nav-jobs",
            "href": "\/jobs?med=site-ui&ref=jobs-tab",
            "class": "-link js-gps-track",
            "data-gps-track": "top_nav.click({is_current:false, location:2, destination:6})"
        }
    }
]
0 голосов
/ 05 февраля 2018

Стоит помнить, что при сканировании внешних ссылок (я ценю, что ОП относится к собственной странице пользователя), вы должны знать о файле robots.txt. Я нашел следующее, которое, надеюсь, поможет http://www.the -art-of-web.com / php / parse-robots / .

0 голосов
/ 12 января 2018

Я придумал следующий код паука.Я немного адаптировал это из следующего: PHP - есть ли безопасный способ выполнить глубокую рекурсию? это кажется довольно быстрым ....

    <?php
function  spider( $base_url , $search_urls=array() ) {
    $queue[] = $base_url;
    $done           =   array();
    $found_urls     =   array();
    while($queue) {
            $link = array_shift($queue);
            if(!is_array($link)) {
                $done[] = $link;
                foreach( $search_urls as $s) { if (strstr( $link , $s )) { $found_urls[] = $link; } }
                if( empty($search_urls)) { $found_urls[] = $link; }
                if(!empty($link )) {
echo 'LINK:::'.$link;
                      $content =    file_get_contents( $link );
//echo 'P:::'.$content;
                    preg_match_all('~<a.*?href="(.*?)".*?>~', $content, $sublink);
                    if (!in_array($sublink , $done) && !in_array($sublink , $queue)  ) {
                           $queue[] = $sublink;
                    }
                }
            } else {
                    $result=array();
                    $return = array();
                    // flatten multi dimensional array of URLs to one dimensional.
                    while(count($link)) {
                         $value = array_shift($link);
                         if(is_array($value))
                             foreach($value as $sub)
                                $link[] = $sub;
                         else
                               $return[] = $value;
                     }
                     // now loop over one dimensional array.
                     foreach($return as $link) {
                                // echo 'L::'.$link;
                                // url may be in form <a href.. so extract what's in the href bit.
                                preg_match_all('/<a[^>]+href=([\'"])(?<href>.+?)\1[^>]*>/i', $link, $result);
                                if ( isset( $result['href'][0] )) { $link = $result['href'][0]; }
                                // add the new URL to the queue.
                                if( (!strstr( $link , "http")) && (!in_array($base_url.$link , $done)) && (!in_array($base_url.$link , $queue)) ) {
                                     $queue[]=$base_url.$link;
                                } else {
                                    if ( (strstr( $link , $base_url  ))  && (!in_array($base_url.$link , $done)) && (!in_array($base_url.$link , $queue)) ) {
                                         $queue[] = $link;
                                    }
                                }
                      }
            }
    }


    return $found_urls;
}    


    $base_url       =   'https://www.houseofcheese.co.uk/';
    $search_urls    =   array(  $base_url.'acatalog/' );
    $done = spider( $base_url  , $search_urls  );

    //
    // RESULT
    //
    //
    echo '<br /><br />';
    echo 'RESULT:::';
    foreach(  $done as $r )  {
        echo 'URL:::'.$r.'<br />';
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...