Делать это исключительно с xpath
Я бы не советовал. Прежде всего, у вас есть белый и черный список. Не совсем понятно, чего вы хотите, поэтому я предполагаю, что со временем это может измениться.
Итак, вы можете сначала выбрать все href
рассматриваемые атрибуты и вернуть узлы. Вот для чего очень хорош Xpath, поэтому давайте используем xpath:
if (!$links = $xpath->query('//a/@href')) {
throw new Exception('XPath query failed.');
}
Теперь у вас есть общий DOMNodeList
в $links
, и он содержит ноль или более DOMAttr
элементов, как мы их выбрали. Теперь им нужна фильтрация, которую вы ищете.
Итак, у вас есть некоторые критерии, которым вы хотите соответствовать. У вас есть подробные, но не очень конкретные, как это должно работать. У вас есть положительное совпадение, а также отрицательные совпадения. Но в обоих случаях вы не говорите, что должно произойти, если нет. Поэтому я делаю ярлык здесь: вы пишете себе функцию, которая возвращает либо true
, либо false
, если строка "href"
соответствует критерию (ам):
function is_valid_href($href) {
// do whatever you see fit ...
return true or false;
}
Таким образом, проблема определения, является ли href
действительным или нет, была решена. Лучшая вещь: вы можете изменить его позже.
Так что все, что нужно, это интегрировать это со ссылками, чтобы получить все ссылки в их нормализованном и абсолютном виде. Это означает больше обработки данных, см .:
для более подробной информации о различных типах нормализации URL.
Итак, мы создаем еще одну функцию, которая инкапсулирует href нормализацию, базовое разрешение и проверку. Если href неверен, он просто возвращает null
, иначе нормализованный href:
function normalize_href($href, $base) {
// do whatever is needed ...
return null or "href string";
}
Давайте соединим это, в моем случае я даже сделаю href экземпляром Net_URL2
, чтобы валидатор мог извлечь из него пользу.
Естественно, если вы заключите это в замыкания или некоторые классы, получится более приятный интерфейс. Также вы можете сделать выражение xpath параметром:
// get all href
if (!$links = $xpath->query('//a/@href')) {
throw new Exception('XPath query failed.');
}
// set a base URL
$base = '/8196211/xpath-query-html-naiti-konkretnye-href-v-tegah-privyazki';
/**
* @return bool
*/
function is_valid_href($href) {
...
}
/**
* @return href
*/
function normalize_href($href, $base) {
...
}
$joblinks = array();
foreach ($links as $attr) {
$href = normalize_href($attr->nodeValue, $base);
if (is_valid_href($href)) {
$joblinks[] = $href;
}
}
// your result is in:
var_dump($joblinks);
Я запустил пример на этом сайте, и результат:
array(122) {
[0]=>
object(Net_URL2)#129 (8) {
["_options":"Net_URL2":private]=>
array(5) {
["strict"]=>
bool(true)
["use_brackets"]=>
bool(true)
["encode_keys"]=>
bool(true)
["input_separator"]=>
string(1) "&"
["output_separator"]=>
string(1) "&"
}
["_scheme":"Net_URL2":private]=>
string(4) "http"
["_userinfo":"Net_URL2":private]=>
bool(false)
["_host":"Net_URL2":private]=>
string(17) "stackexchange.com"
["_port":"Net_URL2":private]=>
bool(false)
["_path":"Net_URL2":private]=>
string(1) "/"
["_query":"Net_URL2":private]=>
bool(false)
["_fragment":"Net_URL2":private]=>
bool(false)
}
[1]=>
...
[121]=>
object(Net_URL2)#250 (8) {
["_options":"Net_URL2":private]=>
array(5) {
["strict"]=>
bool(true)
["use_brackets"]=>
bool(true)
["encode_keys"]=>
bool(true)
["input_separator"]=>
string(1) "&"
["output_separator"]=>
string(1) "&"
}
["_scheme":"Net_URL2":private]=>
string(4) "http"
["_userinfo":"Net_URL2":private]=>
bool(false)
["_host":"Net_URL2":private]=>
string(22) "blog.stackoverflow.com"
["_port":"Net_URL2":private]=>
bool(false)
["_path":"Net_URL2":private]=>
string(30) "/2009/06/attribution-required/"
["_query":"Net_URL2":private]=>
bool(false)
["_fragment":"Net_URL2":private]=>
bool(false)
}
}