PHP获取网站JS文件大小失败:无法读取含../路径及文件不存在错误
解决PHP统计网站JS文件大小无法处理相对路径的问题
嘿,我完全懂你遇到的坑——直接把../test.js这类相对路径丢给file_get_contents时,PHP会把它当成你本地服务器的文件路径去查找,而不是相对于目标网站页面的URL,自然就会报找不到文件的错误。下面是具体的解决方案,一步步来帮你搞定:
核心思路
相对路径是基于当前页面的URL来解析的,不是本地路径。所以我们需要:
- 把页面中的相对JS路径转换成完整的绝对URL
- 通过绝对URL请求远程JS文件,再统计其实际大小
具体实现代码
第一步:编写相对路径转绝对URL的工具函数
这个函数能处理各种类型的相对路径(../test.js、./script.js、/assets/main.js),把它们转换成可直接请求的绝对URL:
function resolve_absolute_url($relative, $base) { $base_parsed = parse_url($base); $relative_parsed = parse_url($relative); // 如果已经是绝对URL,直接返回 if (isset($relative_parsed['scheme'])) { return $relative; } // 处理基础URL的路径:如果是文件路径,取它的目录部分 $base_path = isset($base_parsed['path']) ? $base_parsed['path'] : '/'; if (strpos($base_path, '.') !== false) { $base_path = dirname($base_path); } // 拼接相对路径并解析../和./ $relative_path = isset($relative_parsed['path']) ? $relative_parsed['path'] : ''; $combined_path = rtrim($base_path, '/') . '/' . ltrim($relative_path, '/'); $parts = explode('/', $combined_path); $new_parts = []; foreach ($parts as $part) { if ($part === '..') { array_pop($new_parts); } elseif ($part !== '.') { $new_parts[] = $part; } } $absolute_path = implode('/', $new_parts); // 拼接完整URL,包含协议、主机、端口和查询参数 $absolute_url = "{$base_parsed['scheme']}://{$base_parsed['host']}"; if (isset($base_parsed['port'])) { $absolute_url .= ":{$base_parsed['port']}"; } $absolute_url .= "/".ltrim($absolute_path, '/'); // 保留查询参数(比如?v=1这类缓存标识) if (isset($relative_parsed['query'])) { $absolute_url .= "?{$relative_parsed['query']}"; } return $absolute_url; }
第二步:主流程——解析页面、获取JS并统计大小
这里我们用DOMDocument解析页面中的<script>标签,转换路径后请求文件并计算大小:
// 用户传入的目标网站URL $target_url = 'https://example.com/path/page.html'; // 获取目标页面内容(如果allow_url_fopen关闭,建议用下面的cURL替代) $page_content = file_get_contents($target_url); if (!$page_content) { die('无法加载目标页面,请检查URL是否正确或网络连接'); } // 解析HTML中的script标签(用@忽略不规范HTML的解析警告) $dom = new DOMDocument(); @$dom->loadHTML($page_content); $scripts = $dom->getElementsByTagName('script'); $js_size_stats = []; foreach ($scripts as $script) { $src = $script->getAttribute('src'); if (empty($src)) continue; // 跳过内联脚本 // 转换相对路径为绝对URL $absolute_js_url = resolve_absolute_url($src, $target_url); // 获取JS文件内容(推荐用cURL替代file_get_contents,更稳定) $js_content = @file_get_contents($absolute_js_url); if ($js_content === false) { $js_size_stats[$absolute_js_url] = '请求失败:无法获取该JS文件'; continue; } // 计算大小(字节转KB保留两位小数) $size_bytes = strlen($js_content); $size_kb = round($size_bytes / 1024, 2); $js_size_stats[$absolute_js_url] = "{$size_bytes} 字节 ({$size_kb} KB)"; } // 输出统计结果 echo "<h2>网站JS文件大小统计</h2>"; foreach ($js_size_stats as $url => $info) { echo "<p><strong>{$url}</strong>: {$info}</p>"; }
备选:用cURL替代file_get_contents(更稳定)
如果你的PHP环境关闭了allow_url_fopen,可以用这个函数代替file_get_contents:
function get_remote_content($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_SSL_VERIFYPEER, false); // 根据需求开启/关闭SSL验证 $content = curl_exec($ch); curl_close($ch); return $content; }
然后把主流程里的file_get_contents替换成get_remote_content即可。
注意事项
- 确保PHP的
allow_url_fopen配置开启(如果用file_get_contents的话),或者启用cURL扩展 - 有些网站可能有防盗链机制,直接请求JS文件会失败,这种情况可以在cURL里设置
CURLOPT_HTTPHEADER模拟浏览器请求头 - 解析HTML时用
@忽略警告是因为很多网站的HTML不规范,DOMDocument会抛出大量不影响功能的警告
内容的提问来源于stack exchange,提问作者Noor B.
相关产品推荐
相关产品推荐

