get_meta_tags函数同域/同源获取元信息失败求助
这个问题我之前踩过坑!你遇到的failed to open stream: Redirection limit reached, aborting错误,本质是同域请求触发了服务器的重定向循环——比如你的服务器可能有强制HTTPS、会话认证跳转、或者URL重写规则,导致get_meta_tags发起的HTTP请求陷入无限跳转。跨域请求没问题是因为外部域名的重定向逻辑不会和你的服务器规则冲突,下面给你几个可行的解决方案:
方案1:直接读取本地文件(推荐)
既然是同域页面,本质是服务器上的本地文件,完全不需要通过HTTP请求获取,这种方式不仅能避免重定向问题,还能提升效率。你可以通过输出缓冲捕获目标页面的HTML内容,再用DOM解析meta标签:
// 目标页面的URL $targetUrl = "http://example.com/blog/my-awesome-blog-post"; // 将URL转换为服务器本地文件路径(根据你的框架/路由规则调整) // 示例:替换域名根为服务器文档根目录 $localFilePath = str_replace("http://example.com", $_SERVER['DOCUMENT_ROOT'], $targetUrl); // 如果是URL重写的页面(比如框架路由),需要对应到实际的入口文件,比如Laravel的public/index.php,或者自定义路由解析逻辑 // 用输出缓冲捕获页面内容 ob_start(); // 包含目标页面的PHP文件(注意:如果页面有输出内容,会被ob_start捕获,不会输出到浏览器) include $localFilePath; $htmlContent = ob_get_clean(); // 解析HTML获取meta标签 $dom = new DOMDocument(); @$dom->loadHTML($htmlContent); // @符号忽略HTML解析时的非致命警告 $metaTags = []; foreach ($dom->getElementsByTagName('meta') as $meta) { // 处理name属性的meta标签(如description、keywords) if ($meta->hasAttribute('name')) { $name = strtolower($meta->getAttribute('name')); $metaTags[$name] = $meta->getAttribute('content'); } // 处理property属性的meta标签(如OpenGraph、Twitter Card) elseif ($meta->hasAttribute('property')) { $property = strtolower($meta->getAttribute('property')); $metaTags[$property] = $meta->getAttribute('content'); } } print_r($metaTags);
方案2:用cURL手动控制HTTP请求(适合动态页面无法直接包含的情况)
如果必须通过HTTP请求获取(比如页面逻辑依赖HTTP上下文),可以用cURL替代get_meta_tags,它能更灵活地控制请求参数,避免重定向循环:
$targetUrl = "http://example.com/blog/my-awesome-blog-post"; $ch = curl_init($targetUrl); // 设置返回内容而不是直接输出 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 禁用自动跟随重定向,避免陷入循环 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); // 清空Cookie,避免会话认证导致的跳转(如果不需要认证的话) curl_setopt($ch, CURLOPT_COOKIE, ''); // 模拟浏览器User-Agent,避免服务器对PHP UA做特殊处理 curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"); // 本地环境如果是HTTPS,暂时关闭SSL验证(生产环境建议开启) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); // 手动处理合法重定向(比如HTTPS跳转) if ($httpCode === 301 || $httpCode === 302) { $headers = get_headers($targetUrl, 1); $newUrl = isset($headers['Location']) ? $headers['Location'] : $targetUrl; // 重新请求跳转后的URL $ch = curl_init($newUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_COOKIE, ''); curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"); $htmlContent = curl_exec($ch); curl_close($ch); } else { $htmlContent = $response; } // 同样用DOM解析meta标签 $dom = new DOMDocument(); @$dom->loadHTML($htmlContent); $metaTags = []; foreach ($dom->getElementsByTagName('meta') as $meta) { if ($meta->hasAttribute('name')) { $name = strtolower($meta->getAttribute('name')); $metaTags[$name] = $meta->getAttribute('content'); } elseif ($meta->hasAttribute('property')) { $property = strtolower($meta->getAttribute('property')); $metaTags[$property] = $meta->getAttribute('content'); } } print_r($metaTags);
额外排查点:检查服务器重定向规则
你也可以先排查服务器的配置:比如Apache的.htaccess或Nginx配置里是否有强制HTTPS的规则、URL重写规则是否存在循环,或者是否有针对内部请求的认证跳转逻辑。如果找到导致循环的规则,可以针对性调整,比如允许PHP User-Agent的请求跳过认证,或者调整重定向条件。
内容的提问来源于stack exchange,提问作者saikiran
相关产品推荐
相关产品推荐

