[英]XPath Query & HTML - Find Specific HREF's Within Anchor Tags
我已经在DOMDocument
和DOMXPath
获得了所需的HTML数据。
但是我需要访问和检索某些<a>
标记中的href
值。 以下是标准:
href
包含: some-site.vendor.com/jobs/[#idnumber]/job
[ some-site.vendor.com/jobs/23094/job
]/ 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值。 如果对此问题我没有遵循任何协议,我深表歉意...
任何/所有帮助将不胜感激! 非常感谢!
我不建议仅使用xpath
这样做。 首先,您有一个白名单和一个黑名单。 目前尚不清楚您想要什么,所以我认为这会随着时间而改变。
因此,您可以做的是首先选择所有有问题的href
属性,然后返回节点。 这就是Xpath非常适合的用途,所以让我们使用xpath:
if (!$links = $xpath->query('//a/@href')) {
throw new Exception('XPath query failed.');
}
现在,您在$links
具有公共的DOMNodeList
,并且其中包含零个或多个DOMAttr
元素,因为我们已经选择了这些元素。 这些现在需要您要查找的过滤器。
因此,您有一些想要匹配的黄水晶。 您有冗长但不太明确的说明。 您有正面比赛,也有负面比赛。 但是,在两种情况下,您都不会告诉我们如果没有发生该怎么办。 因此,我在这里做一个快捷方式:您编写了一个函数,如果"href"
字符串与条件匹配,则该函数返回true
或false
:
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)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.