PHP提取单个<p>标签innerHTML并保存为TXT文件遇错求助
如何获取页面唯一
<p>标签内容并保存为TXT文件? 问题背景
你尝试用PHP抓取页面中唯一的<p>标签内容并保存为TXT文件,但使用getElementsByTagName()时遇到了报错,你的代码如下:
<?php $dataPage = file_get_contents('http://www.somedataurl.com'); $doc = new DOMDocument; $doc->loadHTML($dataPage); $dataNodeList = $doc->getElementsByTagName('p'); $dataNode = $dataNodeList->item(0); function innerHTML($node) { return implode(array_map([$node->ownerDocument, "saveHTML"], iterator_to_array($node->childNodes))); } $theData = innerHTML($dataNode); header('Content-Type: text/plain'); $filename = date('Y-m-d') . '.txt'; file_put_contents($filename, $theData); ?>
错误日志显示:
PHP Notice: Undefined property:: DOMNodeList (第10行)
PHP Notice: Undefined property:: DOMNodeList (第11行)
PHP Catchable fatal error (第11行)
你想知道:有没有比getElementsByTagName()更合适的工具?或者调整现有代码能否解决问题?
解决方案
一、调整现有代码修复问题
你的报错根源主要是缺少节点有效性判断:如果页面加载失败、或者实际不存在<p>标签,$dataNode会变成null,此时调用innerHTML(null)就会触发属性未定义的错误。另外,DOMDocument::loadHTML()经常会因为页面HTML格式不规范抛出警告,也需要处理。
修改后的代码如下:
<?php $dataPage = file_get_contents('http://www.somedataurl.com'); // 先检查页面是否成功获取 if (!$dataPage) { die("无法加载目标页面内容"); } $doc = new DOMDocument; // 抑制HTML格式不规范导致的警告 @$doc->loadHTML($dataPage); $dataNodeList = $doc->getElementsByTagName('p'); // 确认存在<p>节点再继续执行 if ($dataNodeList->length === 0) { die("页面中未找到<p>标签"); } $dataNode = $dataNodeList->item(0); function innerHTML($node) { // 增加节点有效性判断,避免传入null报错 if (!$node) return ''; return implode(array_map([$node->ownerDocument, "saveHTML"], iterator_to_array($node->childNodes))); } $theData = innerHTML($dataNode); $filename = date('Y-m-d') . '.txt'; file_put_contents($filename, $theData); // 如需浏览器直接下载文件,保留以下header header('Content-Type: text/plain'); header('Content-Disposition: attachment; filename="' . $filename . '"'); echo $theData; ?>
二、使用更高效的工具:DOMXPath
因为页面只有一个<p>标签,用DOMXPath可以直接精准定位目标节点,代码更简洁直观,省去了节点列表遍历的步骤:
<?php $dataPage = file_get_contents('http://www.somedataurl.com'); if (!$dataPage) { die("无法加载目标页面内容"); } $doc = new DOMDocument; @$doc->loadHTML($dataPage); $xpath = new DOMXPath($doc); // 直接选取页面中的<p>节点(因为只有一个,就是目标节点) $dataNode = $xpath->query('//p')->item(0); if (!$dataNode) { die("页面中未找到<p>标签"); } // PHP 8.0+版本可以直接用内置的innerHTML属性,无需自定义函数 if (method_exists($dataNode, 'innerHTML')) { $theData = $dataNode->innerHTML; } else { $theData = implode(array_map([$doc, "saveHTML"], iterator_to_array($dataNode->childNodes))); } $filename = date('Y-m-d') . '.txt'; file_put_contents($filename, $theData); header('Content-Type: text/plain'); header('Content-Disposition: attachment; filename="' . $filename . '"'); echo $theData; ?>
注意:PHP 8.0及以上版本的DOMElement新增了原生innerHTML属性,可以直接用$dataNode->innerHTML获取内容,省去了自定义函数的麻烦。
内容的提问来源于stack exchange,提问作者Arash Howaida
相关产品推荐
相关产品推荐

