PHP文章采集URL补全函数(FormatUrl)

向北走
向北走
发布时间:2026-10-15 | 2人浏览过
原创

在进行网页数据采集时,经常遇到HTML源码中包含相对路径(如 `./index.htm`)或根路径(如 `/path/file.html`),导致直接请求返回错误或页面失效。本教程提供一个PHP工具函数 `formaturl`,通过解析基础URL并结合正则替换,自动将所有资源链接补全为完整的绝对路径。

问题背景与路径类型

开发采集程序时,目标页面往往使用非绝对路径引用资源。常见的路径格式包括:

  • 相对路径:以 ../ 或 ./ 开头,或直接不加前缀(相对于当前文档位置)。
  • 绝对根路径:以 / 开头,表示从网站根目录开始的路径。
  • 绝对全路径:包含协议、域名和完整路径(如 http://www.xxx.com/path/xxx.html)。

为了正确收集所有资源地址,需要将前两种类型的路径统一转换为第三种“绝对全路径”。

核心操作顺序

第1步:准备基础环境

确保运行环境支持标准PHP库函数(如 parse_url, preg_match_all)。该函数不依赖第三方扩展,适用于大多数PHP版本。

第2步:导入完整代码

将以下函数代码添加到你的采集脚本文件中。代码包含两个函数:formaturl 用于主流程处理,lIIIIl 作为内部辅助函数处理单个标签的URL补全。

<?php
function formaturl($l1,$l2){
    if (preg_match_all("/<img[^>]+src=\"([^\"]+)\"[^>]*>)|(<a[^>]+href=\"([^\"]+)\"[^>]*>)|(<img[^>]+src='([^']+)'[^>]*>)|(<a[^>]+href='([^']+)'[^>]*>)/i",$l1,$regs)){
        foreach($regs[0] as $num => $url){
            $l1 = str_replace($url,lIIIIl($url,$l2),$l1);
        }
    }
    return $l1;
}
function lIIIIl($l1,$l2){
    if(preg_match("/(.*)(href|src)\=(.+?)( |\/\>|\>).*/i",$l1,$regs)){$I2 = $regs[3];}
    if(strlen($I2)>0){
        $I1 = str_replace(chr(34),"",$I2);
        $I1 = str_replace(chr(39),"",$I1);
    }else{return $l1;}
    $url_parsed = parse_url($l2);
    $scheme = $url_parsed["scheme"];if($scheme!=""){$scheme = $scheme."://";}
    $host = $url_parsed["host"];
    $l3 = $scheme.$host;
    if(strlen($l3)==0){return $l1;}
    $path = dirname($url_parsed["path"]);if($path[0]=="\\\\"){$path="";}
    $pos = strpos($I1,"#");
    if($pos>0) $I1 = substr($I1,0,$pos);
    //判断类型
    if(preg_match("/^(http|https|ftp):(\/\/|\\\\)(([\w\/\\\\+\-~`@:%])+\.)+([\w\/\\\\\.\=\?\+\-~`@\':!%#]|(&amp;)|&)+/i",$I1)){return $l1; }//http开头的url类型要跳过
    elseif($I1[0]=="/"){$I1 = $l3.$I1;}//绝对路径
    elseif(substr($I1,0,3)=="../"){//相对路径
        while(substr($I1,0,3)=="../"){
            $I1 = substr($I1,strlen($I1)-(strlen($I1)-3),strlen($I1)-3);
            if(strlen($path)>0){
                $path = dirname($path);
            }
        }
        $I1 = $l3.$path."/".$I1;
    }
    elseif(substr($I1,0,2)=="./"){ 
        $I1 = $l3.$path.substr($I1,strlen($I1)-(strlen($I1)-1),strlen($I1)-1);
    }
    elseif(strtolower(substr($I1,0,7))=="mailto:"||strtolower(substr($I1,0,11))=="javascript:"){ 
        return $l1;
    }else{
        $I1 = $l3.$path."/".$I1;
    }
    return str_replace($I2,"\"$I1\"",$l1);
}
?>

第3步:调用并验证结果

在主程序中定义基准URL(通常为目标页面的首页地址),并将抓取到的HTML片段传入 formaturl 函数即可。

复制代码 代码如下:
<?php
$surl="https://www.example.com/";
$gethtm = '<a href="/index.htm">首页</a><a href="Resolvent/index.htm">解决方案</a>';
echo formaturl($gethtm,$surl);
?>

输出预期:

<a href="https://www.example.com/index.htm">首页</a><a href="https://www.example.com/Resolvent/index.htm">解决方案</a>

完成判断与注意事项

当输出的HTML中所有 href 和 src 均以基准域名开头时,即表示URL补全成功。需注意:

  • 该函数仅处理标准的HTTP/HTTPS路径转换,对 mailto: 和 javascript: 等协议保持不变。
  • 若基础URL缺少协议头,解析可能失败,建议始终传入完整的初始URL(含 http:// 或 https://)。
  • 正则表达式主要针对双引号和单引号包裹的属性值进行了兼容,复杂嵌套场景需结合实际HTML结构微调。

简要总结

通过上述 formaturl 函数,可有效解决PHP采集过程中遇到的资源路径断裂问题。它将复杂的相对路径逻辑封装为简单调用,大幅提升采集脚本的稳定性。以上就是PHP文章采集URL补全函数FormatUrl实现的详细内容,更多关于PHP网页采集的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表