PHP使用Simple Html DOM抓取Skroutz页面无输出问题咨询
问题1:请求skroutz.gr无输出的核心原因
- 直接原因是站点反爬拦截:Simple HTML DOM内置的
file_get_html()方法底层调用PHP原生file_get_contents()发请求,默认请求头里的User-Agent为PHP版本标识,和正常浏览器的请求特征完全不符,skroutz.gr的反爬规则会直接拦截这类异常请求,返回403状态码或空响应。 - 无输出的逻辑:
file_get_html()请求失败时不会抛出显式报错,只会返回布尔值false,PHP中直接echo false不会产生任何可见输出,最终表现为页面空白、无报错信息。 - 其他站点可正常访问的原因:维基百科等站点未对无标准UA的基础请求做严格拦截,所以请求可以正常返回。
问题2:现有代码的问题与修正方案
现有代码的库引入逻辑没有致命错误,仅存在写法冗余问题,核心缺陷集中在远程请求实现上:
- 冗余点:手动定义
$hard_path拼接路径的写法多余,虽然PHP兼容路径中的双斜杠、不会导致文件引入失败,但完全可以简化写法,不需要额外定义路径变量。 - 核心缺陷:直接使用
file_get_html()发起远程请求时,无法自定义请求头、超时时间、跳转规则等参数,完全无法绕过站点的基础反爬校验。
修正方案
放弃使用file_get_html()直接请求远程URL,改用cURL扩展模拟正常浏览器的请求特征拿到HTML字符串,再调用Simple HTML DOM的str_get_html()方法加载字符串完成解析,全程增加状态判断方便排查问题,修正后的完整代码如下:
<?php // 简化库文件引入写法 require_once getcwd() . '/simple_html_dom.php'; $targetUrl = 'https://www.skroutz.gr/s/36232462/Asus-TUF-Dash-F15-FX516PC-HN004W-15-6-FHD-144Hz-i7-11370H-16GB-512GB-SSD-GeForce-RTX-3050-W11-Home-US-Keyboard.html?from=home_price_drops'; // 初始化cURL模拟浏览器请求 $ch = curl_init($targetUrl); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, // 响应内容以字符串形式返回,不直接输出 CURLOPT_FOLLOWLOCATION => true, // 自动跟随3xx跳转 CURLOPT_TIMEOUT => 15, // 总请求超时时间15秒 CURLOPT_CONNECTTIMEOUT => 10, // 连接建立超时时间10秒 CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36', // 传入正常Chrome浏览器的UA CURLOPT_HTTPHEADER => [ 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language: en-US,en;q=0.5', 'Referer: https://www.skroutz.gr/' ], CURLOPT_SSL_VERIFYPEER => false // 本地调试若遇SSL证书校验问题可保留该配置,生产环境建议开启 ]); $htmlContent = curl_exec($ch); $curlError = curl_error($ch); curl_close($ch); // 校验请求状态 if ($curlError) { exit("请求出错:" . $curlError); } if (!$htmlContent) { exit("未获取到有效页面内容"); } // 加载HTML内容生成DOM对象 $dom = str_get_html($htmlContent); if (!$dom) { exit("HTML内容解析失败"); } // 输出页面内容 echo $dom; // 释放DOM对象占用内存,避免内存泄漏 $dom->clear(); unset($dom);
补充说明
- 如果配置完正常请求头仍然无法获取内容,大概率是请求所用IP被站点拦截,更换为普通家用宽带IP或添加合法代理即可解决。
- Simple HTML DOM的
file_get_html()方法仅适合读取本地HTML文件,请求远程地址优先使用cURL等可控性更高的HTTP客户端拿到内容后再做解析。
内容的提问来源于stack exchange,提问作者Periklis Kakarakidis
相关产品推荐
相关产品推荐

