3

当检测到 CURLOPT_CONNECTTIMEOUT 和 CURLOPT_TIMEOUT 时,我想检测、捕获并做一些事情。

我该怎么做呢 ?

我有以下标题:

public static $userAgents = array(
    'FireFox3' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9) Gecko/2008052906 Firefox/3.0',
    'GoogleBot' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
    'IE7' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
    'Netscape' => 'Mozilla/4.8 [en] (Windows NT 6.0; U)',
    'Opera' => 'Opera/9.25 (Windows NT 6.0; U; en)'
);
public static $options = array(
    CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
    CURLOPT_AUTOREFERER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FRESH_CONNECT => true,
    CURLOPT_COOKIEJAR => "cookies.txt",
    CURLOPT_COOKIEFILE => "cookies.txt",
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 300,
        //CURLOPT_COOKIESESSION => false,
);

和以下函数,其中 $res 是一个包含 html 文件名的数组

public function multiCurl($res, $options = "") {

    if (count($res) <= 0)
        return False;

    $handles = array();

    if (!$options) // add default options
        $options = self::$options;

    // add curl options to each handle
    foreach ($res as $k => $row) {
        $ch{$k} = curl_init();
        $options[CURLOPT_URL] = $row['url'];
        curl_setopt_array($ch{$k}, $options);
        $handles[$k] = $ch{$k};
    }

    $mh = curl_multi_init();

    foreach ($handles as $k => $handle) {
        curl_multi_add_handle($mh, $handle);
    }

    $running_handles = null;
    //execute the handles
    do {
        $status_cme = curl_multi_exec($mh, $running_handles);
    } while ($cme == CURLM_CALL_MULTI_PERFORM);

    while ($running_handles && $status_cme == CURLM_OK) {
        if (curl_multi_select($mh) != -1) {
            do {
                $status_cme = curl_multi_exec($mh, $running_handles);
            } while ($status == CURLM_CALL_MULTI_PERFORM);
        }
    }

    foreach ($res as $k => $row) {
        $res[$k]['error'] = curl_error($handles[$k]);
        if (!empty($res[$k]['error']))
            $res[$k]['data'] = '';
        else {
            //$res[$k]['data'] = curl_multi_getcontent($handles[$k]);  // get results 
            file_put_contents(CRAWLER_FILES . $k . '.html', curl_multi_getcontent($handles[$k]));
        }

        // close current handler
        curl_multi_remove_handle($mh, $handles[$k]);
    }
    curl_multi_close($mh);
    return $res; // return response
}
4

3 回答 3

3

要获取有关请求的信息,您可以查看curl_getinfocurl_multi_info_read

并使用类似的东西:

curl_exec($ch);
if(!curl_errno($ch))
{
 $info = curl_getinfo($ch);
 echo 'Took ' . $info['total_time'] . ' seconds to send a request to ' . $info['url'];
}

在信息数组中,您可以接收以下数据:

  • “网址”
  • “内容类型”
  • “http_code”
  • “header_size”
  • “请求大小”
  • “文件时间”
  • “ssl_verify_result”
  • “重定向计数”
  • “总时间”
  • “名称查找时间”
  • “连接时间”
  • “预转移时间”
  • “大小上传”
  • “大小下载”
  • “速度下载”
  • “速度上传”
  • “下载内容长度”
  • “上传内容长度”
  • “开始传输时间”
  • “重定向时间”
  • “证书信息”
  • “request_header”(仅当 CURLINFO_HEADER_OUT 由先前对 curl_setopt() 的调用设置时才设置)
于 2012-08-27T07:56:17.403 回答
3

您有 2 个选项:

  1. 在从 返回的数组中curl_getinfo($ch),将 与connect_time您用于CURLOPT_CONNECTTIMEOUT选项的值进行比较。您还可以total_time与您使用的值进行比较CURLOPT_TIMEOUT。如果你转储出来,curl_getinfo($ch)你会看到还有一堆其他的计时器,你可以推断出你需要的任何东西。
  2. 使用从返回的字符串curl_error($ch)。如果您的任何*_TIMEOUT选项被命中,这将返回一个字符串,如:

操作在 2001 毫秒后超时,收到 0 个字节

于 2013-02-22T14:28:45.387 回答
1

您可以使用如下函数尝试连接 3 次,如果不成功则停止。每次尝试都会增加超时时间,以防服务器“满”并且只需要一点时间。

public function functionName($attempt = 0) {
    if ($attemp >= 3) {
        return FALSE;
    }
    $TIMEOUT = 1;
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $TIMEOUT + $attempt);
    curl_exec($ch);
    if (!curl_errno($ch)) {
        $info = curl_getinfo($ch);
        if ($info['total_time'] > $TIMEOUT) {
            $this->functionName($attempt++);
        } else {
            return TRUE;
        }
    }
}
于 2016-11-07T18:08:57.293 回答