Регулярные выражения

S
На сайте с 04.11.2012
Offline
18
474

Доброго времени суток.

Помогите составить регулярное выражение. Я парсю контент страницы, нужно получить все внутренние ссылки сайта из контента страницы.

Заранее благодарен =)

siv1987
На сайте с 02.04.2009
Offline
427
#1

#<a[^>]+?href=["\'](\S*?)["\'][^>]*>(.*?)</a>#

[umka]
На сайте с 25.05.2008
Offline
456
#2

siv1987, ТС хочет только внутренние :)

Кстати, вы тоже ощущаете нехватку парсеров в интернете? )

Лог в помощь!
SeVlad
На сайте с 03.11.2008
Offline
1609
#3
[umka:
вы тоже ощущаете нехватку парсеров в интернете? )

Особенно не хватает поисковых систем :)

И это не шутка

Делаю хорошие сайты хорошим людям. Предпочтение коммерческим направлениям. Связь со мной через http://wp.me/P3YHjQ-3.
R
На сайте с 20.02.2015
Offline
59
#4

Одной регуляркой не обойтись.


$host = "www.test.ru";
$links = array();
$content = preg_replace(array("#<!--[\s\S]+?-->#", "#<script[\s\S]+?</script>#i"), "", file_get_contents("http://www.test.ru"));
if (preg_match_all("@<a\s([^>]*)?href\s*=\s*[\"']?([^#>'\"\s]*)[\"']?([^>]*)?>@i", $content, $matches)) {

// убираем www
if (strpos($host, "www.") === 0)
$host = substr($host, 4);

foreach ($matches[2] as $n => $href) {
// атрибуты тега, если надо парсить
$attr = $matches[1][$n]." ".$matches[3][$n];

if (empty($href))
continue;

// не парсим протоколы
if (preg_match("#^(mailto|skype|magnet|ftp):#i", $href))
continue;

// абсолютная ссылки
if (preg_match("#^(https?:)?//(www\.)?([^/]+)(/.*)?$#", $href, $match)) {
if (strcmp($host, strtolower($match[3])) !== 0)
continue;
$href = $match[4];
}

// если относительная не начинается с "/"
if (strpos($href, "/") !== 0)
$href = "/".$href;

//$links[] = $href." | ".$matches[0][$n];
$links[] = "http://".$host.$href;
}
}
print_r($links);
S
На сайте с 04.11.2012
Offline
18
#5
rereg:
Одной регуляркой не обойтись.

$host = "www.test.ru";
$links = array();
$content = preg_replace(array("#<!--[\s\S]+?-->#", "#<script[\s\S]+?</script>#i"), "", file_get_contents("http://www.test.ru"));
if (preg_match_all("@<a\s([^>]*)?href\s*=\s*[\"']?([^#>'\"\s]*)[\"']?([^>]*)?>@i", $content, $matches)) {

// убираем www
if (strpos($host, "www.") === 0)
$host = substr($host, 4);

foreach ($matches[2] as $n => $href) {
// атрибуты тега, если надо парсить
$attr = $matches[1][$n]." ".$matches[3][$n];

if (empty($href))
continue;

// не парсим протоколы
if (preg_match("#^(mailto|skype|magnet|ftp):#i", $href))
continue;

// абсолютная ссылки
if (preg_match("#^(https?:)?//(www\.)?([^/]+)(/.*)?$#", $href, $match)) {
if (strcmp($host, strtolower($match[3])) !== 0)
continue;
$href = $match[4];
}

// если относительная не начинается с "/"
if (strpos($href, "/") !== 0)
$href = "/".$href;

//$links[] = $href." | ".$matches[0][$n];
$links[] = "http://".$host.$href;
}
}
print_r($links);

Спасибо вам за помощь! Вроде всё работает, я конечно его доработал немного чтобы дублей не было и чтобы не собирал ссылки типа javascript:, #

Chaser support
На сайте с 20.10.2014
Offline
12
#6
Sillys:
Спасибо вам за помощь! Вроде всё работает, я конечно его доработал немного чтобы дублей не было и чтобы не собирал ссылки типа javascript:, #

Не забудь еще mailto, skype и якоря, типа <a name>

Chaser (http://chaser.ru) - сервис увеличения телефонной конверсии
S
На сайте с 04.11.2012
Offline
18
#7
Chaser support:
Не забудь еще mailto, skype и якоря, типа <a name>

В том примере кода это есть:


// не парсим протоколы
if (preg_match("#^(mailto|skype|magnet|ftp):#i", $href))
continue;
R
На сайте с 20.02.2015
Offline
59
#8

Этот пример нельзя считать готовым решением, написан на коленке за 15 минут. Если углубится в тему 10 строками кода не обойтись.

Многое не учтено, к примеру тег base и относительные пути когда присутствуют двоеточие "/../path/index.html".

Еще есть такие форматы ссылок: tel|callto:

S1
На сайте с 17.04.2011
Offline
79
#9

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

Лучше или использовать DOM несмотря на скорость, либо искать парсеры готовые в виде библиотек.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий