我得到了DOMDocument
和DOMXPath
中所需的HTML数据。
但我需要访问和检索某些<a>
标签中的href
值。以下是标准:
-
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值。如果我没有遵守这个问题的任何协议,我最谦卑的道歉。。。
任何/所有帮助都将不胜感激!提前感谢!
我不建议只使用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;
}
因此,判断CCD_ 26现在是否有效的问题已经得到解决。最好的办法:你可以稍后更改。
因此,所有需要的是将其与链接集成,以获得所有链接的标准化和绝对形式。这意味着更多的数据处理,请参阅:
- 使用php-domdocument添加根路径的问题
- URL代码和文件集内容
有关不同类型的URL规范化的更多详细信息。
因此,我们创建了另一个函数,它封装了away-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)
}
}