网站结构变更致PHP脚本getElementsByTagName()调用空值报错求助
问题:脚本因网站结构变更报错无法运行
推测目标网站结构变更,导致脚本无法运行,报错信息如下:
Fatal error: Uncaught Error: Call to a member function getElementsByTagName() on null in C:\xampik\htdocs\łamaki\open-triangle.php:177 Stack trace: #0 {main} thrown in C:\xampik\htdocs\łamaki\open-triangle.php on line 177
对应的脚本代码片段:
$tmp = explode('-', $current); $url = $siteURL.'/next/soccer/?year='.$tmp[0].'&month='.$tmp[1].'&day='.$tmp[2]; $dom = new DOMDocument(); $dom->loadHTML(execCURL($url)); $table = $dom->getElementsByTagName('table')->item(0); foreach ($table->getElementsByTagName('tr') as $tr){ ############################ $isVisible = $tr->getAttribute('data-def'); if($isVisible == 1){ $meetingDate = trim($tr->getAttribute('data-dt')); $meetingDate = explode(',', $meetingDate); $meetingTime = $meetingDate[3].':'.$meetingDate[4]; $meetingDate = $meetingDate[0].'.'.$meetingDate[1].'.'.$meetingDate[2];
作为新手,已尝试修改路径链接但问题未解决,请问应修改哪里?有没有解决办法?
解决方案
1. 先搞懂报错原因
报错里的Call to a member function... on null,直白说就是$table是空的——你的脚本想找页面里的第一个<table>标签,但现在网站里要么没这个标签了,要么标签位置变了,导致拿不到表格对象,后续代码自然崩了。
2. 先确认页面内容是否正常拿到
先排查是不是CURL请求没拿到正确的页面内容,在代码里加一段调试:
// 在$dom->loadHTML这行前面加 $htmlContent = execCURL($url); // 打印页面内容,看看是不是正常的网页代码 var_dump($htmlContent); exit;
- 如果输出是空的、乱码,或者是404/验证码页面,那得先解决CURL的问题(比如给请求加浏览器头、Cookie,避开反爬);
- 如果输出是正常的网页HTML,再继续排查结构问题。
3. 查看网站当前的真实结构
把拼接好的$url复制到浏览器地址栏打开,右键点击“检查”打开开发者工具:
- 用左上角的选择元素工具,点击原来显示赛事数据的区域,看看现在数据是放在
<table>里,还是换成了<div>这类容器; - 如果还有
<table>,数一下它是页面里的第几个(索引从0开始); - 看看存储数据的属性有没有变,比如原来的
data-def、data-dt还在不在。
4. 针对性修改代码
场景1:表格还在,但不是第一个了
比如现在要找第二个<table>,把item(0)改成item(1):
$table = $dom->getElementsByTagName('table')->item(1);
场景2:数据换成了div容器,用XPath定位更灵活
如果数据在<div class="match-container">这类带类名的容器里,用DOMXPath定位比直接找标签靠谱:
$dom = new DOMDocument(); $dom->loadHTML($htmlContent); $xpath = new DOMXPath($dom); // 把引号里的内容换成你找到的容器选择器 $container = $xpath->query('//div[@class="match-container"]')->item(0); // 先判断容器是否存在,再继续逻辑 if ($container) { // 把getElementsByTagName里的标签换成你找到的行元素,比如div foreach ($container->getElementsByTagName('div') as $row) { $isVisible = $row->getAttribute('data-def'); // 后续日期处理逻辑,根据新的data-dt格式调整 } } else { echo "找不到数据容器"; }
场景3:先加空值判断,避免直接报错
不管怎么改,先给$table加个判断,防止代码直接崩:
$table = $dom->getElementsByTagName('table')->item(0); // 先确认table存在再循环 if ($table) { foreach ($table->getElementsByTagName('tr') as $tr){ // 原来的逻辑 } } else { echo "页面里找不到表格元素"; }
新手调试小技巧
- 每次只改一处代码,运行看效果,别一次改一堆;
- 用
var_dump()打印每一步的变量,比如var_dump($table),看看是不是拿到了预期的元素; - 开发者工具里可以直接右键标签,复制XPath或者CSS选择器,直接用到代码里。
内容的提问来源于stack exchange,提问作者Guzinek
相关产品推荐
相关产品推荐

