За последние 24 часа нас посетили 17897 программистов и 1613 роботов. Сейчас ищут 1487 программистов ...

Алгоритм отфильтровывания внутренных ссылок

Тема в разделе "Решения, алгоритмы", создана пользователем Cron, 4 авг 2008.

  1. Cron

    Cron Активный пользователь

    С нами с:
    10 июл 2008
    Сообщения:
    289
    Симпатии:
    0
    Адрес:
    Украина, Сумы
    Добрый день. Собственно, возникла задачка интересная, связанная с индексированием содержания сайта.
    Нужна функция, которая принимает два аргумента:
    1) адрес ссылки, которую мы нашли в HTML коде-страницы.
    2) абсолютная ссылка той страницы, на которой мы сейчас находимся.

    Функция должна вернуть:
    1) FALSE, в случае, если ссылка является внешней, либо имеет протокол ftp://, ftps://, https://. Собственно это уже сделано. Это не сложно. Интереснее следующий пункт.
    2) Если функция не вернула FALSE, то необходимо вернуть абсолютный путь первой полученной ссылки.

    Например назовем isInside($url, $main).
    Тогда
    PHP:
    1. isInside('http://www.google.ru/about.html', 'http://www.moysite.com/index.php') = FALSE //внешняя ссылка
    PHP:
    1. isInside('about.php', 'http://www.moysite.com/index.php') = [url=http://www.moysite.com/about.php]http://www.moysite.com/about.php[/url]
    Может кто уже имел дело с подобным? Подскажите пжл. Потому что с виду кажеться просто, а начал писать немного запутался в разнообразии ситуаций. Функция получается загроможденная и ужасно непонятная. Да и то, некоторые моменты пропускает.
    Может у кого есть решение или мысли как это сделать красиво? Заранее благодарен.
     
  2. Anonymous

    Anonymous Guest

    угу. ты тег <base> учтываешь? )
     
  3. Cron

    Cron Активный пользователь

    С нами с:
    10 июл 2008
    Сообщения:
    289
    Симпатии:
    0
    Адрес:
    Украина, Сумы
    Горбунов Олег
    Спасибо за подсказку. :) До этого еще не добрался. Тут хоть бы с иерархическим заданием адреса разобраться.
     
  4. NOmeR1

    NOmeR1 Активный пользователь

    С нами с:
    11 май 2008
    Сообщения:
    97
    Симпатии:
    0
  5. Cron

    Cron Активный пользователь

    С нами с:
    10 июл 2008
    Сообщения:
    289
    Симпатии:
    0
    Адрес:
    Украина, Сумы
    Спасибо за наводку. ;) Буду разбираться.
     
  6. NOmeR1

    NOmeR1 Активный пользователь

    С нами с:
    11 май 2008
    Сообщения:
    97
    Симпатии:
    0
    А нечего разбираться :)
    Функция JoinToSite в моём скрипте - то, что тебе нужно.
     
  7. Cron

    Cron Активный пользователь

    С нами с:
    10 июл 2008
    Сообщения:
    289
    Симпатии:
    0
    Адрес:
    Украина, Сумы
    Да я уже понял.
    Только вот не пойму как она обрабатывает рекурсивное задание. Ну ссылки, типа "../about.php"
    И Олег Горбунов был прав - есть же еще BASE, который тоже надо учитывать.
     
  8. AlexGousev

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    PHP:
    1. <?php
    2. /**
    3.  * Схлопывет путь: удаляет ../ и ./ из пути, не привязываясь к файловой системе
    4.  *
    5.  * @version 1.0
    6.  * @author Alex S Gousev <alex@gousev.ru>
    7.  *
    8.  * @param string $path путь в unix-формате
    9.  * @return string|bool схлопнутый путь или false, если невозможно схлопнуть ../
    10.  */
    11. function path_collapse($path) {
    12.     # Избавляемся от ./
    13.     $path = preg_replace('%(\A|/)(?:\./)+%', '\1', $path);
    14.    
    15.     # Избавляемся от ../
    16.     while ($pos = strpos($path, '/../'))
    17.         $path = preg_replace('%(\A|/)[^/]+/\.\./%', '\1', $path);
    18.    
    19.     if (preg_match('%\A/?\.\./%', $path))
    20.         return false;
    21.  
    22.     return $path;
    23. }
    24. ?>
     
  9. NOmeR1

    NOmeR1 Активный пользователь

    С нами с:
    11 май 2008
    Сообщения:
    97
    Симпатии:
    0
    Код (Text):
    1. <?php
    2. function isInside($url, $site) {
    3.     $domain = parse_url($site);
    4.     $domain = $domain['scheme'].'://'.$domain['host'];
    5.     if($url{0} == '/') {
    6.         $link = $domain.$url;
    7.     } else if(preg_match('~^http(s)?:~i', $url)) {
    8.         if(parse_url($url, PHP_URL_HOST) == parse_url($site, PHP_URL_HOST)) {
    9.             $link = $url;
    10.         }
    11.     } else {
    12.         if(!preg_match('~^(ftp(s)?|javascript|mailto):~i',     $url)) {
    13.             $dirname = '';
    14.             $explode = explode('/', parse_url($site, PHP_URL_PATH));
    15.             foreach($explode as $i => $dir) {
    16.                 if($dir && $i != (count($explode)-1)) {
    17.                     $dirname .= $dir.'/';
    18.                 }
    19.             }
    20.             $link = $domain.'/'.$dirname.preg_replace('~(\A|/)\./~', '$1', $url);
    21.             $regex = '~/(?!\.\./)[^\x2F]+/\.\./~';
    22.             while(preg_match($regex, $link)) {
    23.                 $link = preg_replace($regex, '/', $link);
    24.             }
    25.         }
    26.     }
    27.     return (isset($link) ? $link : false);
    28. }
    29. echo isInside('../../../phpinfo.html', 'http://php.ru/it/is/test/index.php');
    30. ?>
    Немного обновил скрипт. Кому интересно, заходите сюда:
    http://forum.antichat.ru/showpost.php?p ... tcount=413
     
  10. Cron

    Cron Активный пользователь

    С нами с:
    10 июл 2008
    Сообщения:
    289
    Симпатии:
    0
    Адрес:
    Украина, Сумы
    NOmeR1
    Спасибо огромное. Очень помогло.
     
  11. EvelRus

    EvelRus Активный пользователь

    С нами с:
    16 ноя 2006
    Сообщения:
    2.168
    Симпатии:
    0
    Адрес:
    Москва
    NOmeR1, только не с сайта, а со страницы!
     
  12. NOmeR1

    NOmeR1 Активный пользователь

    С нами с:
    11 май 2008
    Сообщения:
    97
    Симпатии:
    0
    Ты немного не понял. Он утаскивает ссылки, начиная со страницы, которую ты сам объявишь в скрипте, заканчивая той, на которой новых ссылок нет.

    Вот пример. К примеру у тебя на компе есть файлы:

    Код (Text):
    1. [Урл файла]         =>  [ссылки, указанные в файлах данного урла]
    2.  
    3. 1.html            =>    1.html, 2.html
    4. 2.html            =>    5.html, 6.html
    5. 3.html            =>    1.html, 2.html
    6. 4.html            =>    4.html, page/1.html
    7. 5.html            =>    6.html, 3.html
    8. 6.html            =>    1.html, 4.html
    9. 7.html            =>    7.html, page/3.html
    10. page/1.html       =>    2.html, ../1.html
    11. page/2.html       =>    1.html, ../7.html
    12. page/3.html       =>    1.html, 2.html
    Если ты, в качестве начальной ссылки, указываешь 1.html, то на выводе будет примерно такое:

    Код (Text):
    1. http://localhost/1.html
    2. http://localhost/2.html
    3. http://localhost/3.html
    4. http://localhost/4.html
    5. http://localhost/5.html
    6. http://localhost/6.html
    7. http://localhost/7.html
    8. http://locahost/page/1.html
    9. http://locahost/page/2.html
    10. http://locahost/page/3.html
    Причём всё выдирается и выдаётся без повторений.