如何用XPath获取子段落内容并合并为单字符串?PHP实现遇阻
解决PHP DOM获取指定div下所有p标签文本的问题
我看你遇到的问题主要出在两个关键地方:一是XPath的class匹配逻辑不够严谨,二是全局查询所有目标p标签后用索引对应$facts的方式容易出错,毕竟没法保证两组查询的结果数量完全对应上。咱们一步步来修正:
首先,修正XPath的class匹配逻辑
你原来用contains(@class, 'b-list-fact__item-explanation js-fact-explanation')的写法有隐患——如果目标元素的class属性里这两个类的顺序变了,或者多了其他类,这个匹配就会失效。正确的写法应该是用空格包裹类名,确保匹配完整的类:
// 精准匹配同时包含两个类的div $divs = $finder->query("//div[contains(concat(' ', normalize-space(@class), ' '), ' b-list-fact__item-explanation ') and contains(concat(' ', normalize-space(@class), ' '), ' js-fact-explanation ')]");
然后,针对每个div单独获取内部p标签的文本
不要全局查询所有p标签,而是遍历每个匹配到的div,再在这个div的上下文里查询p标签,这样能保证每个div对应的p文本都能正确收集,然后合并成单个字符串:
完整示例代码
$html = file_get_contents('https://...'); $html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'); $dom = new DOMDocument; @$dom->loadHTML($html); $finder = new DomXPath($dom); // 先匹配所有目标div $divs = $finder->query("//div[contains(concat(' ', normalize-space(@class), ' '), ' b-list-fact__item-explanation ') and contains(concat(' ', normalize-space(@class), ' '), ' js-fact-explanation ')]"); $dataArr = []; // 遍历每个div,收集并合并内部p标签的文本 foreach ($divs as $div) { $ps = $finder->query(".//p", $div); $mergedText = ''; foreach ($ps as $p) { // 去除每个p文本的首尾空白后拼接 $mergedText .= trim($p->textContent) . ' '; } // 最后清理整体多余空格 $mergedText = trim($mergedText); $dataArr[] = $mergedText; } // 如果你还要关联原来的$facts标题,建议在对应上下文查询(假设标题和解释div是关联节点) $facts = $finder->query("//a[contains(concat(' ', normalize-space(@class), ' '), ' b-list-fact__item-text ')]"); foreach ($facts as $fact) { $factText = trim(str_replace("\n", " ", $fact->textContent)); $dataArr[] = $factText; // 获取当前标题对应的解释div(假设是标题的下一个兄弟节点,可根据实际结构调整) $relatedDiv = $finder->query("./following-sibling::div[contains(concat(' ', normalize-space(@class), ' '), ' b-list-fact__item-explanation ')]", $fact)->item(0); if ($relatedDiv) { $ps = $finder->query(".//p", $relatedDiv); $mergedText = ''; foreach ($ps as $p) { $mergedText .= trim($p->textContent) . ' '; } $dataArr[] = trim($mergedText); } }
为什么之前的写法失效?
- 你的XPath匹配class的方式不够健壮,容易因为class属性的顺序变化、额外类的添加导致匹配不到目标div
- 全局查询所有p标签后用
$long_fact[$key]对应$facts条目,一旦两组结果数量不匹配(比如有的div无p标签、有的条目无对应div),就会出现索引错误或获取错误文本 - 当你用
//p/text()查询时,返回的是文本节点集合而非元素节点,调用textContent会出错,应该直接取nodeValue
内容的提问来源于stack exchange,提问作者Ricardo
相关产品推荐
相关产品推荐

