话不多说,先贡献代码。
<?php
// 相对URL转绝对URL
function url2absolute($href, $currentUrl = '')
{
// 去除前后空格,如果是 空字符串,锚点,或者议协议开头 则没必要继续解析下去了
$href = trim($href);
if ($href === '' || strpos($href, '#') === 0) {
return $currentUrl ? $currentUrl : $href;
}
if (preg_match('/^[a-z]+:/i', $href)) {
return $href;
}
// 结果路径
$url = '';
// 转换所有 '\'
$url = preg_replace('/\\\\/', '/', $href);
// 去除所有 './'
$url = preg_replace('/(?<!\.)\.\//', '', $url);
// 迭代去除所有的 '/abc/../'
$patternUpper = '/(?<!\/)\/([^\/]{1,}?)\/\.\.\//';
$count = preg_match_all($patternUpper, $url, $matches);
do {
$url = preg_replace($patternUpper, '/', $url);
$count = preg_match_all($patternUpper, $url, $matches);
} while ($count >= 1);
// 除去最后的 '/..'
$url = preg_replace('/(?<!\/)\/([^\/]{1,}?)\/\.\.$/', '/', $url);
$url = preg_replace('/\/\.\.$/', '', $url);
// 除去存在的 '../'
$url = preg_replace('/(?<!\.)\.\.\//', '', $url);
// 替换域名
if (stripos($url, 'http') !== 0 && $currentUrl) {
// 解析当前URL
if (filter_var($currentUrl, FILTER_VALIDATE_URL)) {
if (strpos($url, '/') === 0) {
$currentUrlPart = parse_url($currentUrl);
$currentUrlDomain = $currentUrlPart['scheme'] . '://' . $currentUrlPart['host'] . (isset($currentUrlPart['port']) ? (':' . $currentUrlPart['port']) : '');
$url = rtrim($currentUrlDomain, '/') . '/' . ltrim($url, '/');
} else {
$url = rtrim($currentUrl, '/') . '/' . $url;
}
}
}
return $url;
}
$href = '/a/b/../a/../c/../a/./a/../a/';
$currentUrl = 'https://138.139.90.1:8888/summary/';
var_dump(url2absolute($href, $currentUrl));
PS:
之前在做爬虫的时候,遇到那种href不全的网站,需要去手动拼接。后面我自己写了一个函数fix,效果还是不行(自己写得烂,当时没啥思路)。今天闲暇时,有想起这个问题,然后网上找找看,找到了这篇文章 https://www.jb51.net/article/106971.htm ,思路中规中矩的,膜拜大佬。本文函数中间部分借鉴了前辈的代码。
头和尾是我加上去优化的,方便使用。
- Prev: Redis 数据类型及操作
- Next: 注册域名的一些心得