CURL GET POST MULTI
CURL小结
个人将归纳curl请求总结成三步
1、创建curl 句柄(curl_init),并设置参数(curl_setopt)(打开冰箱)
2、执行请求(curl_exec),处理返回的数据 (把大象塞进去)
3、关闭curl(curl_close),释放所有资源(关上冰箱)
其实如果代码看起来比较复杂,复杂的地方可能就是在处理返回数据的逻辑。
CURL_SETOPT
故名思议,SetOption 设置参数,其中囊括的参数较多,这里只是简单提取常用的几个,如需查看更多参数,点击link,常见的设置 UA、Cookie、https等
bool curl_setopt ( resource $ch , int $option , mixed $value )
CURLOPT_USERAGENT 在HTTP请求中包含一个"User-Agent: "头的字符串。
CURLOPT_REFERER 在HTTP请求头中"Referer: "的内容。
CURLOPT_TIMEOUT 允许 cURL 函数执行的最长秒数。
CURLOPT_RETURNTRANSFER TRUE 将curl_exec()获取的信息以字符串返回,而不是直接输出。
/*下面两个再https请求中才需设置*/
CURLOPT_SSL_VERIFYPEER FALSE 禁止 cURL 验证对等证书(peer's certificate)。要验证的交换证书可以
在CURLOPT_CAINFO 选项中设置,或在 CURLOPT_CAPATH中设置证书目录。(自cURL 7.10开始默认为 TRUE。从 cURL
7.10开始默认绑定安装。)
CURLOPT_SSL_VERIFYHOST 设置为 1 是检查服务器SSL证书中是否存在一个公用名(common name)。译者注:公用
名(Common Name)一般来讲就是填写你将要申请SSL证书的域名 (domain)或子域名(sub domain)。 设置成 2,会检查公
用名是否存在,并且是否与提供的主机名匹配。 0 为不检查名称。 在生产环境中,这个值应该是 2(默认值)。值1的支持在
cURL 7.28.1 中被删除了。
如需返回的Header头,自行添加
curl_setopt($curl, CURLOPT_HEADER, 1);
判断返回的状态码:
curl_getinfo($curl, CURLINFO_HTTP_CODE)
if(curl_getinfo($curl, CURLINFO_HTTP_CODE) == '200')
分离返回 header和body
curl_setopt($curl, CURLOPT_HEADER, 1);
list($sHeader, $sBody) = explode("\r\n\r\n", $sRet, 2);
GET
简单版的Get请求如下:
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://www.baidu.com');
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$sData = curl_exec($curl);
curl_close($curl);
var_dump($sData);
稍微复杂的设置了UA、Cookie等,https请求中才需要只用的SSL证书校验,http请求中可不用,如果需要请求有规律的地址,类似https://example.com/?id=$i,修改for循环即可。
class getRequest
{
const sUA = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)';
const sURL = 'https://www.baidu.com';
const sCookie = 'fake if you want';
function vInitRequest()
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_HEADER, self::sUA);
curl_setopt($curl, CURLOPT_COOKIE, self::sCookie);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
/*
* ssl check,use for https url
*/
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);
// for ($iId = 1; $iId < 1000; $iId++) {
// $sURL = self::sURL.$iId;
curl_setopt($curl, CURLOPT_URL, self::sURL);
$this->sExecRequest($curl);
// }
}
function sExecRequest($curl)
{
$sRet = curl_exec($curl);
print_r($sRet);
/**
* handle your response
* stripos or preg
*/
curl_close($curl);
}
}
$foo = new getRequest();
$foo->vInitRequest();
POST
POST请求无非比上述Get请求多设置了两个参数。
1、嘿,我要用POST提交数据了。
2、我POST的数据的内容
代码如下:
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, array('user'=>'test'));
简单的例子:
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://www.baidu.com');
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
$aPostData = array(
'username' => 'test',
.....
);
curl_setopt($curl, CURLOPT_POSTFIELDS, $aPostData);
$sData = curl_exec($curl);
curl_close($curl);
var_dump($sData);
CURL_MULTI_EXEC
curl_multi_exec可同时执行多个请求,如果你网络请求速度很快,网站相应的速度超过你处理Response的速度,建议采用curl_multi_exec,步骤很简单。代码如下
curl_multi_init();//初始化
curl_multi_add_handle()//添加句柄
curl_multi_exec// 批量执行
这里以爬取百度验证码图片为例:
ini_set("memory_limit", '-1');
date_default_timezone_set("PRC");
class multiGetRequest
{
const sUA = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)';
const sURL = 'https://passport.baidu.com/cgi-bin/genimage?
njGeb06e22aefd4de7a02671411de01f513c021a606ee0400d3';
const sCookie = 'fake if you want';
const sDir = '/Users/test/Desktop/baidu/'; //你自己的路径
const iCurlCount = 100; //爬取图片张数
private $sMicrotime = '';
function vInitMultiCurl(){
$this->sMicrotime = microtime(true);
$sMultiCurlResource = curl_multi_init();
$this->vInitCurl($sMultiCurlResource);
}
function vInitCurl($sMultiCurlResource){
$i = 0;
while ($i != self::iCurlCount) {
$aCurlResource[$i] = curl_init(self::sURL);
curl_setopt($aCurlResource[$i], CURLOPT_RETURNTRANSFER, 1);
curl_setopt($aCurlResource[$i], CURLOPT_HEADER, 1);
curl_setopt($aCurlResource[$i], CURLOPT_TIMEOUT, 200);
curl_multi_add_handle($sMultiCurlResource, $aCurlResource[$i]);
$i++;
}
$this->vExecCurl($aCurlResource, $sMultiCurlResource);
}
function vExecCurl($aCurlResource, $sMultiCurlResource){
$iIsRunning = 0;
do {
$sMultiResource = curl_multi_exec($sMultiCurlResource, $iIsRunning);
curl_multi_select($sMultiCurlResource);
} while ($iIsRunning > 0 || $sMultiResource == CURLM_CALL_MULTI_PERFORM);
foreach ($aCurlResource as $i => $rCurl) {
$aRes[$i] = curl_multi_getcontent($rCurl);
}
$this->vHandleResponse($aRes);
}
function vHandleResponse($aRes){
var_dump(count($aRes));
foreach ($aRes as $sReponse) {
list($header, $body) = explode("\r\n\r\n", $sReponse, 2);
$sCode = strtotime(time()).rand(1,1000000);
file_put_contents(self::sDir . $sCode . '.jpg', $body);
}
var_dump(('消时:' . round(microtime(true) - $this->sMicrotime, 3)));
}
}
$foo = new multiGetRequest();
$foo->vInitMultiCurl();