Simple HTML DOM加载指定URL失败,始终返回默认首页求助
我正在用PHP搭配Simple HTML DOM Parser抓取Autotrader的房车经销商页面,比如初始URL是https://www.autotrader.co.uk/motorhomes/motorhome-dealers/bc-motorhomes-ayr-dpp-10004733?channel=motorhomes&page=5。用以下代码能正常加载目标页面:
$html = new simple_html_dom(); $html->load_file($url);
我写了一个函数获取下一页链接,它能正确返回page=6的目标URL(https://www.autotrader.co.uk/motorhomes/motorhome-dealers/bc-motorhomes-ayr-dpp-10004733?channel=motorhomes&page=6):
function getNextLink($_htmlTemp) { //Getting the next page links $aNext = $_htmlTemp->find('a.next', 0); $nextLink = $aNext->href; return $nextLink; }
但问题来了:当我在循环里用$originalHtml->load_file($nxtLink)加载这个正确的下一页链接时,却总是拿到不带page参数的默认首页。完整循环代码如下:
$originalHtml = $html; $shouldLoop = true; //Main Array $value = array(); do{ $listings = $originalHtml->find('div.searchResult'); foreach($listings as $item) { //Some logic here } //After loop we will have details of all the listing in this page -- so get next page link $nxtLink = getNextLink($originalHtml); //Returns string url if(!empty($nxtLink)) { //Yay, we have the next link -- load the next link print 'Next Url: '.$nxtLink.'<br>'; //$nxtLink has correct value $originalHtml->load_file($nxtLink); //This line fetches default page } else { //No next link -- stop the loop as we have covered all the pages $shouldLoop = false; } } while($shouldLoop);
我已经尝试过编码整个URL或仅编码查询参数,也试过创建新的Simple HTML DOM实例加载文件,但问题依旧,恳请协助解决。
解决方案思路
这种情况大概率是网站的反爬机制拦截了你的请求,或者是load_file默认的请求头太简单,服务器识别为非浏览器请求直接返回首页。给你几个可行的解决方向:
1. 用cURL模拟浏览器请求,再加载内容
Simple HTML DOM的load_file方法请求头非常简陋,很容易被反爬识别。建议先用cURL获取页面内容(带上浏览器级别的请求头),再用load方法加载:
function getPageContent($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 模拟Chrome浏览器的请求头 curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', '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: ' . $url, 'Connection: keep-alive' ]); // 开启cookie维持会话,避免被判定为新请求 curl_setopt($ch, CURLOPT_COOKIEJAR, 'autotrader_cookies.txt'); curl_setopt($ch, CURLOPT_COOKIEFILE, 'autotrader_cookies.txt'); $content = curl_exec($ch); curl_close($ch); return $content; } // 替换初始加载逻辑 $htmlContent = getPageContent($url); $html->load($htmlContent); // 循环里加载下一页也用同样方式 if(!empty($nxtLink)) { print 'Next Url: '.$nxtLink.'<br>'; $nextPageContent = getPageContent($nxtLink); $originalHtml->load($nextPageContent); }
2. 检查并补全相对路径
有时候$aNext->href可能返回相对路径(比如?channel=motorhomes&page=6),直接用load_file会加载错误地址。可以在获取链接时补全域名:
function getNextLink($_htmlTemp) { $aNext = $_htmlTemp->find('a.next', 0); $nextLink = $aNext->href; // 检查是否为完整URL,不是则拼接基础域名 if(strpos($nextLink, 'http') !== 0) { $baseUrl = 'https://www.autotrader.co.uk'; $nextLink = $baseUrl . $nextLink; } return $nextLink; }
3. 每次加载新页面时创建新实例
复用同一个simple_html_dom实例可能会残留旧数据或缓存,导致加载异常。可以在循环里销毁旧实例并创建新的:
if(!empty($nxtLink)) { print 'Next Url: '.$nxtLink.'<br>'; // 清理旧实例 $originalHtml->clear(); // 创建新实例加载内容 $originalHtml = new simple_html_dom(); $nextPageContent = getPageContent($nxtLink); $originalHtml->load($nextPageContent); }
内容的提问来源于stack exchange,提问作者Shubham SSJ

