正如其他人已经指出的那样,您的电话查询将产生多个节点,但您的extractNodeValue
函数只返回其中一个。我的建议是像这样重写它:
function extractNodeValue($query, $xPath, $attribute = null) {
$values = array();
foreach($xPath->query("//{$query}") as $node) {
$values[] = $attribute ? $node->getAttribute($attribute) : $node->nodeValue;
}
return join($values, ", ");
}
这将返回单个逗号分隔字符串中的多个值,但更改分隔符很容易,或者如果这对您更有用,则将值作为数组返回。
我还建议去掉此处添加到查询中的“//”,并将其包含在调用代码中。否则,在某些情况下,您最终会被添加两次。但这并不是在这一点上修复的必要条件。
至于电话查询本身,您的查询取决于电话 div 处于某些固定位置,这根本不可靠(在某些页面上它也匹配网站和电子邮件地址)。
在我看来,您需要匹配两种不同的情况:在“Where”div(eventDetailInfo部分的 div 3)下和“Contact”div(div 4)下。
在 "Where" div 下,电话号码可以在不同的位置,但它们总是有一个 "tel" 类,所以最安全的查询可能是这样的:
//*[@id="eventDetailInfo"]/div[3]/*[@class="tel"]
在“Contact” div 下,电话号码也可以在不同的位置,但在电话 div 上没有任何可以匹配的类。但是,该 div 中的内容始终以字符串“Phone:”开头,因此一种解决方案是使用 XPathstarts-with
函数。
//*[@id="eventDetailInfo"]/div[4]/div[starts-with(.,"Phone:")]
然后,您可以将这两个查询与 union ( |
) 运算符结合起来以涵盖这两种情况。或者(我认为这是一个更好的解决方案),您可以通过使其更通用来对这两种情况使用第二个查询,如下所示:
//*[@id="eventDetailInfo"]//div[starts-with(.,"Phone:")]
一个可能的缺点是这不再将搜索限制为“Where”和“Contact”div,因此如果eventDetailInfo部分的其他部分有电话号码,它也会匹配那些(尽管这可能是一件好事) .
请注意,即使没有联合,此查询仍会在某些页面上返回多个节点。extractNodeValue
因此,无论哪种方式,如果要获取所有值,使用更新的函数至关重要。