То, что вы (вероятно) хотите использовать, называется «рекурсия».
Веб-страницы - это графики.Существует несколько алгоритмов трансверсальности графов;самое простое для понимания - глубина в начале.
Скажем, ваш сайт выглядит так (рекурсия прекращена):
* http://example.com/
* http://example.com/
* ...
* http://example.com/post/1/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/archives/
* ...
* http://example.com/post/2/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/archives/
* ...
* http://example.com/post/3/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/archives/
* ...
* http://example.com/about/
* http://example.com/
* ...
* http://example.com/archives/
* http://example.com/archives/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/post/1/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/archives/
* ...
* http://example.com/post/2/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/archives/
* ...
* http://example.com/post/3/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/archives/
* ...
* http://example.com/post/4/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/archives/
* ...
* http://example.com/post/5/
* http://example.com/
* ...
* http://example.com/about/
* ...
* http://example.com/archives/
* ...
Когда вы впервые нажимаете http://example.com/,, у вас естьследующие ссылки:
Вам необходимо отслеживать страницы, которые вы уже посетили, чтобы их можно было игнорировать.(В противном случае это заняло бы целую вечность паука страницы ... буквально.) Вы добавляете в список игнорирования каждый раз, когда вы посещаете страницу.Прямо сейчас единственная запись в списке игнорирования - это http://example.com/.
Далее вы отфильтровываете игнорируемые ссылки, сокращая список до:
Затем вы снова запускаете сборщик на каждом изэти ссылки.Вы делаете это, вызывая вашу функцию снова, с текущим URL и списком игнорируемых сообщений: spider($url, &$ignoredUrls)
(Мы используем ссылку на $ignoredUrls
, поэтому вновь игнорируемые элементы видны родительским вызовам spider
.)
Глядя на http://example.com/post/1/,, мы видим следующие ссылки:
Мы уже рассмотрели http://example.com/. Следующая ссылка, которая не игнорируется, - это страница about.Со страницы about мы переходим на страницу архивов, где просматриваем каждое сообщение.Каждый пост имеет одинаковый набор ссылок:
Потому что мыуже посетили все эти ссылки, мы возвращаем пустой массив.
Вернемся к /archives/
, мы добавляем ссылку /post/2/
(первая незамеченная ссылка в /archives/
) к локальной $foundLinks
переменная, а также возвращаемое значение вызова spider
on с /post/2/
(который является пустым массивом).Затем мы переходим ко второму сообщению.
Когда мы просматриваем все наши сообщения, мы возвращаем $foundLinks
.Страница /about/
затем добавляет эти ссылки к своей собственной $foundLinks
, в дополнение к ссылке /about/
.Поток возвращается к /post/1/
, который смотрит на /archives/
(который теперь игнорируется).Паук /posts/1/
теперь завершен и возвращает свой собственный $foundLinks
.В конце концов, исходный вызов получает все найденные ссылки.
Этот метод отлично работает для небольшого сайта, который полностью закрыт.Если вы перейдете по ссылке на Википедию, вы будете пауковать весь день.Вы можете бороться с этой проблемой по крайней мере двумя способами:
- Прекращение паутинга после определенной глубины (например, 10 ссылок).
- Ограничение URL-адресов, например, для определенного домена или субдомена(как
example.com
).
Вот быстрая реализация spider
(не проверено):
function get_urls($url) {
// curl/DOM code here
}
define('SPIDER_MAX_DEPTH', 10);
function spider_internal($url, &$ignoredUrls, $depth = 0) {
$foundUrls = array($url);
$ignoredUrls[] = $foundUrls;
if($depth >= SPIDER_MAX_DEPTH) {
return $foundUrls;
}
$links = get_links($url);
foreach($links as $link) {
if(array_search($link, $ignoredUrls) !== false) {
continue;
}
$foundUrls = array_merge($foundUrls, spider($link, $ignoredUrls, $depth + 1));
}
return $foundUrls;
}
function spider($url) {
$ignoredUrls = array();
return spider_internal($url, $ignoredUrls);
}