PHP爬取URL中href属性问题:一级深度爬取无结果求助
嘿,我来帮你排查下为什么你的findAndCompare函数没返回任何结果。从你描述的需求和给出的代码片段来看,大概率是踩了几个PHP网页爬取的常见坑,咱们一步步拆解问题:
1. 输入URL的协议补全与格式验证
首先,用户输入的URL很可能没带http://或https://(比如只输入example.com),这时候你的爬取逻辑会把它当成相对路径,直接导致请求失败。
建议在获取website1的输入值后,先做协议补全和格式校验:
$inputUrl = $_POST['website1'] ?? ''; // 补全缺失的HTTP/HTTPS协议 if (!preg_match("~^(?:f|ht)tps?://~i", $inputUrl)) { $inputUrl = "https://" . $inputUrl; } // 验证URL格式是否合法 if (!filter_var($inputUrl, FILTER_VALIDATE_URL)) { die("请输入有效的网站URL(比如:https://example.com)"); }
2. findAndCompare函数的HTML解析逻辑缺陷
如果你用正则表达式匹配<a>标签的href,很容易因为HTML结构的不规范(比如标签内有空格、单引号包裹href、特殊字符)导致匹配失效。强烈建议用DOMDocument替代正则,这是处理HTML最可靠的方式。
示例解析逻辑(可以整合到你的函数里):
function extractHrefs($targetUrl) { $hrefList = []; $dom = new DOMDocument(); // 屏蔽HTML解析时的警告(很多网站的HTML并不完全符合标准) libxml_use_internal_errors(true); // 用更稳定的cURL获取页面内容(替代file_get_contents) $htmlContent = getPageContent($targetUrl); if (!$htmlContent) return $hrefList; $dom->loadHTML($htmlContent); libxml_clear_errors(); // 遍历所有<a>标签提取href $links = $dom->getElementsByTagName('a'); foreach ($links as $link) { $rawHref = $link->getAttribute('href'); if (empty($rawHref)) continue; // 把相对路径转换为绝对路径 $absoluteHref = convertToAbsoluteUrl($targetUrl, $rawHref); $hrefList[] = $absoluteHref; } // 去重避免重复链接 return array_unique($hrefList); } // 辅助函数:转换相对路径为绝对路径 function convertToAbsoluteUrl($baseUrl, $relativeUrl) { $parsedBase = parse_url($baseUrl); if (strpos($relativeUrl, 'http') === 0) { return $relativeUrl; // 已经是绝对路径 } elseif (strpos($relativeUrl, '/') === 0) { return $parsedBase['scheme'] . '://' . $parsedBase['host'] . $relativeUrl; } else { $basePath = dirname($parsedBase['path'] ?? '/'); return $parsedBase['scheme'] . '://' . $parsedBase['host'] . $basePath . '/' . $relativeUrl; } } // 辅助函数:用cURL获取页面内容(避免被反爬) function getPageContent($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向 curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/114.0.0.0 Safari/537.36'); // 模拟浏览器UA curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 设置超时时间 $content = curl_exec($ch); curl_close($ch); return $content; }
3. 一级深度爬取的流程漏洞
一级深度爬取需要先爬取首页的所有链接,再逐个爬取这些链接对应的页面并提取href。如果你的findAndCompare函数没实现这个递进逻辑,或者在爬取子页面时遇到请求失败(比如反爬、404),也会返回空结果。
建议的完整流程:
- 第一步:提取首页的所有绝对路径href
- 第二步:遍历首页的href列表,逐个调用
extractHrefs函数提取子页面的href - 第三步:汇总首页和子页面的href结果(可以分开存储区分层级)
4. 表单提交的潜在问题
你代码里用<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>作为表单action,虽然做了转义,但如果脚本文件名包含特殊字符,可能导致提交异常。可以替换成更稳定的写法:
<form action="<?php echo htmlspecialchars($_SERVER['SCRIPT_NAME']);?>" method="post">
或者直接写action="",浏览器会自动提交到当前页面。
最后建议你先做单步测试:比如固定一个已知可用的URL(比如https://example.com),调用extractHrefs函数看是否能返回正常结果,确认解析逻辑没问题后,再整合表单提交和一级爬取的完整流程。
内容的提问来源于stack exchange,提问作者elliot_m

