phpdr.net/php-curlmulti

此包已被废弃,不再维护。作者建议使用ares333/php-curl包。

最佳php curl库。

维护者

详细信息

github.com/ares333/php-curl

源码

问题

安装数: 1,994

依赖项: 0

建议者: 0

安全: 0

星标: 432

关注者: 44

分支: 188

开放问题: 0

v4.6.1 2018-12-13 03:47 UTC

README

关于

使用php-curl内部IO事件实现,具有高性能、高通用性、高可扩展性,特别适用于大量任务和复杂逻辑场景。

需求

PHP: >=5.3

安装

composer require ares333/php-curl

特性

  1. 极低的CPU和内存消耗。
  2. 直接暴露所有curl选项,实现高通用性和高可扩展性。
  3. API非常简单。
  4. 支持进程中断和从上次运行状态恢复。
  5. 支持动态任务。
  6. 支持透明文件缓存。
  7. 支持自动重试失败的任务。
  8. 支持全局配置、任务配置、回调配置格式相同,优先级从低到高。
  9. 所有配置都可以即时更改并立即生效。

工作流程

Curl::add()向任务池添加任务。Curl::start()启动事件循环并阻塞。onSuccess、onFail、onInfo、onTask...事件将被触发,并即时调用回调。当所有任务完成后,循环结束。

教程

基本

use Ares333\Curl\Curl;
$curl = new Curl();
$curl->add(
    array(
        'opt' => array(
            CURLOPT_URL => 'http://baidu.com',
            CURLOPT_RETURNTRANSFER => true
        ),
        'args' => 'This is user argument'
    ),
    function ($r, $args) {
        echo "Request success for " . $r['info']['url'] . "\n";
        echo "\nHeader info:\n";
        print_r($r['info']);
        echo "\nRaw header:\n";
        print_r($r['header']);
        echo "\nArgs:\n";
        print_r($args);
        echo "\n\nBody size:\n";
        echo strlen($r['body']) . ' bytes';
        echo "\n";
    });
$curl->start();

文件下载

use Ares333\Curl\Curl;
$curl = new Curl();
$url = 'https://www.baidu.com/img/bd_logo1.png';
$file = __DIR__ . '/download.png';
// $fp is closed automatically on download finished.
$fp = fopen($file, 'w');
$curl->add(
    array(
        'opt' => array(
            CURLOPT_URL => $url,
            CURLOPT_FILE => $fp,
            CURLOPT_HEADER => false
        ),
        'args' => array(
            'file' => $file
        )
    ),
    function ($r, $args) {
        if($r['info']['http_code']==200) {
            echo "download finished successfully, file=$args[file]\n";
        }else{
            echo "download failed\n";
        }
    })->start();

任务回调

任务可以在任务回调中添加。更多详细信息请参阅Curl::$onTask。

use Ares333\Curl\Toolkit;
use Ares333\Curl\Curl;
$toolkit = new Toolkit();
$toolkit->setCurl();
$curl = $toolkit->getCurl();
$curl->maxThread = 1;
$curl->onTask = function ($curl) {
    static $i = 0;
    if ($i >= 50) {
        return;
    }
    $url = 'http://www.baidu.com';
    /** @var Curl $curl */
    $curl->add(
        array(
            'opt' => array(
                CURLOPT_URL => $url . '?wd=' . $i ++
            )
        ));
};
$curl->start();

运行信息

use Ares333\Curl\Toolkit;
use Ares333\Curl\Curl;
$curl = new Curl();
$toolkit = new Toolkit();
$curl->onInfo = array(
    $toolkit,
    'onInfo'
);
$curl->maxThread = 2;
$url = 'http://www.baidu.com';
for ($i = 0; $i < 100; $i ++) {
    $curl->add(
        array(
            'opt' => array(
                CURLOPT_URL => $url . '?wd=' . $i
            )
        ));
}
$curl->start();

在命令行运行并将以下格式输出

SPD    DWN  FNH  CACHE  RUN  ACTIVE  POOL  QUEUE  TASK  FAIL  
457KB  3MB  24   0      3    3       73    0      100   0

'onInfo'回调将接收所有信息。默认回调只显示部分信息。

SPD:Download speed
DWN:Bytes downloaded
FNH:Task count which has finished
CACHE:Cache count which were used 
RUN:Task running count
ACTIVE:Task count which has IO activities
POOL:Task count in task pool
QUEUE:Task count which has finished and waiting for onSuccess callback to process
TASK:Task count has been added to the task pool
FAIL:Task count which has failed after retry.

透明缓存

use Ares333\Curl\Toolkit;
use Ares333\Curl\Curl;
$curl = new Curl();
$toolkit = new Toolkit();
$curl->onInfo = array(
    $toolkit,
    'onInfo'
);
$curl->maxThread = 2;
$curl->cache['enable'] = true;
$curl->cache['dir'] = __DIR__ . '/output/cache';
if (! is_dir($curl->cache['dir'])) {
    mkdir($curl->cache['dir'], 0755, true);
}
$url = 'http://www.baidu.com';
for ($i = 0; $i < 20; $i ++) {
    $curl->add(
        array(
            'opt' => array(
                CURLOPT_URL => $url . '?wd=' . $i
            )
        ));
}
$curl->start();

运行脚本第二次时将输出:

SPD  DWN  FNH  CACHE  RUN  ACTIVE  POOL  QUEUE  TASK  FAIL  
0KB  0MB  20   20     0    0       0     0      20    0

结果指示所有任务都在使用缓存,没有网络活动。

动态任务

use Ares333\Curl\Curl;
$curl = new Curl();
$url = 'http://baidu.com';
$curl->add(array(
    'opt' => array(
        CURLOPT_URL => $url
    )
), 'cb1');
echo "add $url\n";
$curl->start();

function cb1($r)
{
    echo "finish " . $r['info']['url'] . "\n";
    $url = 'http://bing.com';
    $r['curl']->add(
        array(
            'opt' => array(
                CURLOPT_URL => $url
            )
        ), 'cb2');
    echo "add $url\n";
}

function cb2($r)
{
    echo "finish " . $r['info']['url'] . "\n";
}

输出如下

add http://baidu.com
finish https://www.baidu.com/
add http://bing.com
finish http://cn.bing.com/

完成的URL以'/'后缀结尾,因为curl已自动处理3xx重定向(Curl::$opt[CURLOPT_FOLLOWLOCATION]=true)。应使用Curl::onTask来处理大量任务。

Curl (src/Curl.php 核心功能)

public $maxThread = 10

最大工作并行数,可动态更改。

public $maxTry = 3

触发onFail事件前的最大重试次数。

public $opt = array ()

全局CURLOPT_*,可由任务配置覆盖。

public $cache = array(
    'enable' => false,
    'compress' => 0, //0-9,6 is a good choice if you want use compress.
    'dir' => null, //Cache dir which must exists.
    'expire' => 86400,
    'verifyPost' => false //If http post will be part of cache id.
);

全局缓存配置。缓存ID从URL映射。配置可由任务配置和onSuccess回调返回值以相同格式覆盖。

public $taskPoolType = 'queue'

堆栈或队列。

public $onTask = null

当工作并行数小于Curl::$maxThread且任务池为空时触发。回调参数是当前Curl实例。

public $onInfo = null

运行状态回调在IO事件上触发,最大频率为1/s。参数如下

  1. $info数组,包含两个键'mall'和'running'。键'running'包含每个运行任务的响应头(curl_getinfo())。键'all'包含全局信息,键如下
    • $info['all']['downloadSpeed'] 下载速度。
    • $info['all']['bodySize'] 已下载的正文大小。
    • $info['all']['headerSize'] 已下载的头部大小。
    • $info['all']['activeNum'] 有IO活动的任务数。
    • $info['all']['queueNum'] 等待onSuccess的任务数量。
    • $info['all']['finishNum'] 已完成任务数量。
    • $info['all']['cacheNum'] 缓存命中次数。
    • $info['all']['failNum'] 重试后失败的任务数量。
    • $info['all']['taskNum'] 任务池中的任务数量。
    • $info['all']['taskRunningNum'] 正在运行的任务数量。
    • $info['all']['taskPoolNum'] 任务池数量。
    • $info['all']['taskFailNum'] 重试的任务数量。
  2. 当前的Curl实例。
  3. 是否是最后调用。
public $onEvent = null

在IO事件上触发。回调参数是当前的Curl实例。

public $onFail = null

全局失败的回调函数,可以被任务'onTask'覆盖。回调接收两个参数。

  1. 具有以下键的数组:
  • errorCode CURLE_* 常量。
  • errorMsg 错误信息。
  • info 响应头。
  • curl 当前的Curl实例。
  1. $item['args'] 从Curl::add()获取的值。
public function add(array $item, $onSuccess = null, $onFail = null, $ahead = null)

将一个任务添加到池中。

  • $item
    1. $item['opt']=array() 当前任务的CURLOPT_*。
    2. $item['args'] 回调参数。
    3. $item['cache']=array() 当前任务的缓存配置。
  • $onSuccess 在任务完成时触发。
    • 回调有两个参数:
      1. $result 包含以下键的数组
        • $result['info'] 响应头。
        • $result['curl'] 当前的Curl实例。
        • $result['body'] 响应体。在下载任务中不存在。
        • $result['header'] 原始响应头。当CURLOPT_HEADER被启用时存在。
        • $result['cacheFile'] 当使用缓存时存在。
      2. 来自 $item['args'] 的值
    • 可以返回的值。如果存在,必须是数组。数组键如下
      • cache 与Curl::$cache相同的格式。这是最后控制缓存的机会。
  • $onFail 覆盖Curl::$onFail。
  • $ahead 是否添加到高优先级队列。

返回:当前的Curl实例。

public function start()

启动事件循环并阻塞。

public function stop()

停止事件循环并返回未处理的任务。

public function parseResponse($response)

解析响应中的http头和体。

public function getCacheFile($url, $post = null)

生成相对缓存路径。

工具包(src/Toolkit.php 必要工具)

function setCurl($curl = null)

如果$curl为null,则使用默认的Curl实例。

默认实例将初始化Curl::$opt,Curl::onInfo,Curl::onFail。Curl::$opt的初始值如下

array(
    CURLINFO_HEADER_OUT => true,
    CURLOPT_HEADER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_AUTOREFERER => true,
    CURLOPT_USERAGENT => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_MAXREDIRS => 5
)
function onFail($error, $args)

默认失败回调。有关详细信息,请参阅Curl::$onFail。

function onInfo($info)

默认info回调。有关详细信息,请参阅Curl::onInfo。

该方法可以通过字符串参数手动触发,该参数将被添加到输出缓冲区。目的是避免shell控制字符的干扰。

function htmlEncode($html, $in = null, $out = 'UTF-8', $mode = 'auto')

强大的HTML编码转换器,可以自动获取当前编码并替换中的HTML编码值。参数:

  • $html HTML字符串。
  • $in 当前编码。最好指定一个。
  • $out 目标编码。
  • $mode auto|iconv|mb_convert_encoding。

返回:新的编码HTML。

function isUrl($url)

是否是完整URL。返回bool。

function formatUrl($url)

替换空格,处理方案和主机,并删除锚点等。

function buildUrl(array $parse)

parse_url()的逆函数。

function uri2url($uri, $urlCurrent)

将uri转换为currentPage的完整URL.$urlCurrent在3xx后应该被重定向。

function url2uri($url, $urlCurrent)

将完整URL转换为currentPage的uri.$urlCurrent在3xx后应该被重定向。

function url2dir($url)

将完整URL转换为dir.$urlCurrent在3xx后应该被重定向。

function url2absolute($url, $urlCurrent)

将基础URL和相对URL组合成新的绝对URL。

function urlRemoveDotSegments($path)

从URL的路径中过滤出"."和".."段,并返回结果。

function getCurl()

返回当前的Curl实例。