XPath Query & HTML – поиск конкретных HREF в пределах якорных тегов

У меня есть данные HTML, необходимые в DOMDocument и DOMXPath .

Но мне нужно получить и получить значения href в определенных тегах <a> . Ниже приведены критерии:

  1. href содержит: some-site.vendor.com/jobs/[#idnumber]/job (т.е. some-site.vendor.com/jobs/23094/job )

  2. href не содержит: some-site.vendor.com/jobs/search?search=pr2

  3. href не содержит: some-site.vendor.com/jobs/intro

  4. href не содержит: www.someothersite.com/

  5. href не содержит: media.someothersite.com/

  6. href не содержит: javascript:void(0)

Любой из этих (похожих) запросов извлекает все, кроме 4-6 – это хорошо:

 $joblinks = $xpath->query('//a[@href[contains(., "https://some-site.vendor.com/jobs/")]]'); $joblinks = $xpath->query('//a[@href[contains(., "job")]]'); 

В конечном счете, однако, мне нужно получить доступ ко всем привязным тегам, содержащим href, как # 1, и назначить фактические значения href внутри переменной / массиву. Вот что я делаю:

 $payload = fetchRemoteData(SPEC_SOURCE_URL); // suppress warning(s) due to malformed markup libxml_use_internal_errors(true); // load the fetched contents $dom = new DOMDocument(); $dom->preserveWhiteSpace = false; $dom->loadHTML($payload); // parse and cache the required data elements $xpath = new DOMXPath($dom); //$joblinks = $xpath->query('//a[@href[contains(., "some-site.vendor.com/jobs/")]]'); $joblinks = $xpath->query('//a[@href[contains(., "job")]]'); foreach($joblinks as $joblink) { var_dump(trim($joblink->nodeValue)); // dump hrefs here! } echo "\n"; 

Это действительно избивает меня – я близок, но я просто не могу правильно настроить запрос и / или получить доступ к фактическим значениям href. Мои самые смиренные извинения, если я не следил за протоколом любого рода для этого вопроса …

ЛЮБОЕ / ВСЕ помощь будет принята с благодарностью! Thanx SO MUCH заранее!

Solutions Collecting From Web of "XPath Query & HTML – поиск конкретных HREF в пределах якорных тегов"

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

Итак, что вы можете сделать, это сначала выбрать все атрибуты href в вопросе и вернуть узлы. Это то, к чему подходит Xpath, поэтому давайте использовать xpath:

 if (!$links = $xpath->query('//a/@href')) { throw new Exception('XPath query failed.'); } 

Теперь у вас есть общий DOMNodeList в $links DOMNodeList и он содержит нулевые или более элементы DOMAttr как мы их выбрали. Теперь вам нужна фильтрация, которую вы ищете.

Итак, у вас есть какая-то критика, которую вы хотите сопоставить. У вас есть многословная, но не очень конкретная информация о том, как это должно работать. У вас положительный матч, но и отрицательные. Но в обоих случаях вы не говорите, что должно произойти, если нет. Итак, я делаю ярлык здесь: вы пишете себе функцию, которая возвращает true или false если строка "href" соответствует критериям (критериям):

 function is_valid_href($href) { // do whatever you see fit ... return true or false; } 

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

Итак, все, что нужно, это интегрировать это со ссылками, чтобы получить все ссылки в их нормализованной и абсолютной форме. Это означает больше обработки данных, см.

  • проблема с добавлением корневого пути с использованием php domdocument
  • Urlencode и file_get_contents

для получения более подробной информации о различных типах нормализации 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 = 'https://stackoverflow.com/questions/9894956/xpath-query-html-find-specific-hrefs-within-anchor-tags'; /** * @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) } }