У меня есть данные HTML, необходимые в DOMDocument
и DOMXPath
.
Но мне нужно получить и получить значения href
в определенных тегах <a>
. Ниже приведены критерии:
href
содержит: some-site.vendor.com/jobs/[#idnumber]/job
(т.е. some-site.vendor.com/jobs/23094/job
)
href
не содержит: some-site.vendor.com/jobs/search?search=pr2
href
не содержит: some-site.vendor.com/jobs/intro
href
не содержит: www.someothersite.com/
href
не содержит: media.someothersite.com/
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 заранее!
Выполняя это исключительно с помощью 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
действительным или нет, была решена. Лучше всего: вы можете изменить его позже.
Итак, все, что нужно, это интегрировать это со ссылками, чтобы получить все ссылки в их нормализованной и абсолютной форме. Это означает больше обработки данных, см.
для получения более подробной информации о различных типах нормализации 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) } }