You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP爬取商品页报Call to a member function find() on bool错误

问题说明

运行PHP商品信息爬取脚本时触发致命错误:

Fatal error: Uncaught Error: Call to a member function find() on bool in C Stack trace: #0 {main} thrown in C on line 16

脚本逻辑为读取Book1.csv中存储的商品编码,拼接生成对应商品详情页URL,借助simple_html_dom库抓取页面.ProductDetailsTable节点下的商品属性信息,写入test.csv文件。此前已成功处理900余条商品编码的爬取任务,运行中途突发报错,暂不确定是否与XAMPP Apache运行环境有关。

原代码如下:

<?php
// example of how to use basic selector to retrieve HTML contents
include('simple_html_dom.php');

$file = fopen("Book1.csv","r");
$file2 = fopen("test.csv","w");
$links = [];

while (($result = fgetcsv($file)) !== false)
{
    $link = "https://mall/Product/".$result[0];
    $links[] = $link;

    $row_data = [];
    $page = file_get_html($link);
    $product_details = $page->find('.ProductDetailsTable tr'); //line 16
    if(count($product_details)==0) {
        $row_data[] = $result[0];
        $row_data[] = 'not found'; 
        fputcsv($file2, $row_data);
        continue;
    }

    //second method
    $article_number = '';
    $product_description = '';
    $product_family = '';
    $product_lifecycle = '';
    $plm_date = '';
    $notes = '';
    $EAN = '';
    $UPC = '';
    $country_of_origin = '';

    foreach($product_details as $table_row) {    
        if(count($table_row->find('td'))==1){
            //ignore
        } elseif(count($table_row->find('td'))==2) {
            $key = $table_row->find('td')[0]->plaintext;
            $value = $table_row->find('td')[1]->plaintext;
            if($key=="EAN") {
                $EAN = $value;
            }
            elseif($key=='Article Number (Market Facing Number)') {
                $article_number = $value;
            } elseif ($key=='Product Description') {
                $product_description = $value;
            } elseif ($key=='Product family') {
                $product_family = $value;
            }elseif ($key=='Product Lifecycle (PLM)') {
                $product_lifecycle = $value;
            }elseif ($key=='PLM Effective Date') {
                $plm_date = $value;
            }elseif ($key=='Notes') {
                $notes = $value;
            }elseif ($key=='UPC') {
                $UPC = $value;
            }elseif ($key=='Country of origin') {
                $country_of_origin = $value;
            }    
        } 
    }
    $row_data[] = trim($article_number);
    $row_data[] = trim($product_description);
    $row_data[] = trim($product_family);
    $row_data[] = trim($product_lifecycle);
    $row_data[] = trim($plm_date);
    $row_data[] = trim($notes);
    $row_data[] = trim($EAN);
    $row_data[] = trim($UPC);
    $row_data[] = trim($country_of_origin);
    fputcsv($file2, $row_data);
}

fclose($file);
fclose($file2);
echo 'done';

?>
错误根因

该错误与XAMPP Apache运行环境无关,核心问题是第15行file_get_html($link)调用返回了布尔值false,代码未做返回值校验,直接在第16行对false调用find()方法触发报错。
file_get_html返回false的常见触发场景(与运行900余条后才报错的特征完全匹配):

  • 某条拼接生成的商品URL无效,对应商品已下架/不存在,服务端返回404/500错误
  • 短时间请求频率过高,触发站点反爬策略,返回403拦截页或验证码页
  • 单次请求遭遇网络波动、连接超时,未拿到合法HTML内容
  • simple_html_dom存在内存泄漏问题,连续加载大量HTML文档后未手动释放内存,解析失败返回false
排查思路
  • 打印报错时点正在处理的商品编码和拼接后的URL,直接在浏览器访问确认页面是否正常加载
  • 抓取请求返回的响应状态码,确认失败原因是页面不存在、反爬拦截还是网络异常
  • 打印脚本运行过程中的内存占用,确认是否为内存溢出导致的解析失败
修复方案
  • 增加file_get_html返回值校验,拿到false时直接记录异常,跳过当前条目继续处理,避免整个脚本崩溃
  • 每次处理完单条页面后手动释放simple_html_dom占用的内存,避免连续爬取时内存溢出
  • 增加合理请求间隔,降低被反爬拦截的概率
  • 增加错误标记,记录失败的URL和原因,方便后续补爬

核心修复代码片段参考:

$page = file_get_html($link);
// 新增页面获取失败的兜底逻辑
if ($page === false) {
    $row_data[] = $result[0];
    $row_data[] = 'page fetch failed';
    fputcsv($file2, $row_data);
    $page = null;
    // 增加100ms请求间隔,避免请求过快
    usleep(100000);
    continue;
}
$product_details = $page->find('.ProductDetailsTable tr');
// 原有解析逻辑保持不变

// 单条数据处理完成后,手动释放DOM对象占用内存
$page->clear();
$page = null;
// 请求间隔
usleep(100000);

内容的提问来源于stack exchange,提问作者user19267705

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 21:42:15