You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化PHP双重foreach循环的URL检索脚本以降低服务器负载?

PHP批量页面检查脚本优化方案

先修正原代码的致命bug

原file_get_contents_curl函数中存在参数错误:curl_setopt($curl, CURLOPT_USERAGENT, ...)里的$curl应为$ch,否则User-Agent设置无效,还会产生PHP警告,增加不必要的资源消耗。


核心优化措施

1. 复用Curl句柄,减少连接开销

每次新建Curl连接都会经历TCP三次握手,复用同一句柄能避免重复的连接建立/销毁开销,大幅提升请求效率。

修改后的请求函数:

function get_page_content($url, $ch) {
    curl_setopt($ch, CURLOPT_URL, $url);
    $data = curl_exec($ch);
    return $data;
}

// 初始化一次Curl句柄,全局复用
$ch = curl_init();
$useragent = 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0';
curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// 开启持久化连接,进一步降低连接成本
curl_setopt($ch, CURLOPT_KEEPALIVE, true);
curl_setopt($ch, CURLOPT_TCP_KEEPIDLE, 60);
curl_setopt($ch, CURLOPT_TCP_KEEPINTVL, 60);
// 添加超时设置,避免无响应请求占用资源
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);

// 遍历请求站点
foreach ($sites as $site){
    $homepage = get_page_content($site, $ch);
    if ($homepage === false) {
        error_log("请求失败:$site");
        continue;
    }
    // 后续URL检查逻辑
}

// 最后关闭句柄
curl_close($ch);

2. 用Curl Multi实现并行请求

同步逐个请求会导致服务器长时间处于阻塞等待状态,使用Curl Multi同时发起多个请求,能大幅缩短总执行时间,降低服务器负载。

示例代码:

function fetch_multiple_pages($sites) {
    $multiHandle = curl_multi_init();
    $handles = [];
    $useragent = 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:17.0) Gecko/20100101 Firefox/17.0';

    // 初始化所有请求句柄
    foreach ($sites as $site) {
        $ch = curl_init($site);
        curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_TIMEOUT, 20);
        curl_multi_add_handle($multiHandle, $ch);
        $handles[$site] = $ch;
    }

    // 执行并行请求
    $running = null;
    do {
        curl_multi_exec($multiHandle, $running);
        curl_multi_select($multiHandle);
    } while ($running > 0);

    // 收集结果并清理资源
    $results = [];
    foreach ($handles as $site => $ch) {
        $results[$site] = curl_multi_getcontent($ch);
        curl_multi_remove_handle($multiHandle, $ch);
        curl_close($ch);
    }
    curl_multi_close($multiHandle);

    return $results;
}

// 批量获取所有页面内容
$pageContents = fetch_multiple_pages($sites);

3. 优化URL查找逻辑

原代码对每个页面逐个调用strpos检查所有目标URL,效率低下。将所有目标URL合并为一个正则表达式,一次匹配完成所有检查,减少字符串操作次数。

// 转义URL中的正则特殊字符,避免匹配错误
$escapedUrls = array_map('preg_quote', $urls);
// 构建正则表达式,忽略大小写
$urlPattern = '/(' . implode('|', $escapedUrls) . ')/i';

// 遍历页面内容进行检查
foreach ($pageContents as $site => $homepage) {
    if (!$homepage) continue;
    if (preg_match($urlPattern, $homepage)) {
        echo 'true';
    }
}

4. 限制并发数,避免过载

如果站点数量过多,一次性发起所有请求可能导致服务器端口耗尽或被目标站点封禁。可以分批处理请求,每批控制并发数:

function fetch_pages_in_batches($sites, $batchSize = 10) {
    $results = [];
    // 将站点列表拆分为多个批次
    $siteBatches = array_chunk($sites, $batchSize);

    foreach ($siteBatches as $batch) {
        $batchResults = fetch_multiple_pages($batch);
        $results = array_merge($results, $batchResults);
        // 每批请求后短暂休眠,避免过度请求
        usleep(500000); // 休眠0.5秒
    }

    return $results;
}

// 使用分批请求
$pageContents = fetch_pages_in_batches($sites, 10);

5. 本地缓存静态资源

每次运行脚本都从远程读取站点列表和目标URL,若这些文件不频繁更新,可缓存到本地,减少远程请求开销:

$sitesCache = './sites_cache.txt';
$urlsCache = './urls_cache.txt';
$cacheExpire = 3600; // 缓存有效期1小时

// 读取站点列表,优先使用缓存
if (file_exists($sitesCache) && time() - filemtime($sitesCache) < $cacheExpire) {
    $sites_raw = file($sitesCache);
} else {
    $sites_raw = file('https://earnmoneysafe.com/script/sites.txt');
    file_put_contents($sitesCache, implode("\n", $sites_raw));
}
$sites = array_map('trim', $sites_raw);

// 读取目标URL,同理使用缓存
if (file_exists($urlsCache) && time() - filemtime($urlsCache) < $cacheExpire) {
    $urls_raw = file($urlsCache);
} else {
    $urls_raw = file('https://earnmoneysafe.com/script/4toiskatj.txt');
    file_put_contents($urlsCache, implode("\n", $urls_raw));
}
$urls = array_map('trim', $urls_raw);

内容的提问来源于stack exchange,提问作者Regular User

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:31:23