php curl 防止采集,php多线程采集网页的解决办法 curl多线程采集
一直在使用thinkphp做項(xiàng)目,同樣也經(jīng)常進(jìn)行采集!而對(duì)于物聯(lián)卡來說,就更要大量的采集運(yùn)營(yíng)商提供的API信息,平時(shí)使用PHP單線程curl采集多個(gè)網(wǎng)頁的時(shí)候速度特別慢,尤其是采集幾十個(gè)接口的時(shí)候(電信不提供多個(gè)流量卡同時(shí)調(diào)用數(shù)據(jù)的接口,只能一個(gè)一個(gè)的查詢);這個(gè)速度慢的要死要死的!于是就想到curl多線程采集的問題,最終找到幾個(gè)效果還是很不錯(cuò)的!解決了采集運(yùn)營(yíng)商接口的大難題!測(cè)試了一下,采集20條數(shù)據(jù)的時(shí)間為4秒左右,比平時(shí)要快2倍了!
既然為了學(xué)習(xí),那么先來了解下PHP curl函數(shù)信息:
以下是PHP中cURL多線程相關(guān)函數(shù):
curl_multi_add_handle — 向curl批處理會(huì)話中添加單獨(dú)的curl句柄
curl_multi_close — 關(guān)閉一組cURL句柄
curl_multi_exec — 運(yùn)行當(dāng)前 cURL 句柄的子連接
curl_multi_getcontent — 如果設(shè)置了CURLOPT_RETURNTRANSFER,則返回獲取的輸出的文本流
curl_multi_info_read — 獲取當(dāng)前解析的cURL的相關(guān)傳輸信息
curl_multi_init — 返回一個(gè)新cURL批處理句柄
curl_multi_remove_handle — 移除curl批處理句柄資源中的某個(gè)句柄資源
curl_multi_select — 等待所有cURL批處理中的活動(dòng)連接
curl_multi_setopt — 為 cURL 并行處理設(shè)置一個(gè)選項(xiàng)
curl_multi_strerror — Return string describing error code
一般來說,想到要用這些函數(shù)時(shí),目的顯然應(yīng)該是要同時(shí)請(qǐng)求多個(gè)URL,而不是一個(gè)一個(gè)依次請(qǐng)求,否則不如自己循環(huán)去調(diào)curl_exec好了。
步驟總結(jié)如下:
1、調(diào)用 curl_multi_init,初始化一個(gè)批處理handle
2、循環(huán)調(diào)用 curl_multi_add_handle,往1中的批處理handle 添加curl_init來的子handle
3、持續(xù)調(diào)用 curl_multi_exec,直到所有子handle執(zhí)行完畢。
5、調(diào)用 curl_multi_remove_handle,并為每個(gè)字handle調(diào)用curl_close
好了,直接上函數(shù)(輸入?yún)?shù)為url數(shù)組,返回結(jié)果為對(duì)應(yīng)的網(wǎng)頁源碼數(shù)組)
PHP
function curl_multi($urls) {
if (!is_array($urls) or count($urls) == 0) {
return false;
}
$num=count($urls);
$curl = $curl2 = $text = array();
$handle = curl_multi_init();
function createCh($url) {
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko');//設(shè)置頭部
curl_setopt ($ch, CURLOPT_REFERER, $url); //設(shè)置來源
curl_setopt ($ch, CURLOPT_ENCODING, "gzip"); // 編碼壓縮
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);//是否采集301、302之后的頁面
curl_setopt ($ch, CURLOPT_MAXREDIRS, 5);//查找次數(shù),防止查找太深
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // 對(duì)認(rèn)證證書來源的檢查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // 從證書中檢查SSL加密算法是否存在
curl_setopt ($ch, CURLOPT_TIMEOUT, 20);
curl_setopt ($ch, CURLOPT_HEADER, 0);//輸出頭部
return $ch;
}
foreach($urls as $k=>$v){
$url=$urls[$k];
$curl[$k] = createCh($url);
curl_multi_add_handle ($handle,$curl[$k]);
}
$active = null;
do {
$mrc = curl_multi_exec($handle, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($handle) != -1) {
usleep(100);
}
do {
$mrc = curl_multi_exec($handle, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
foreach ($curl as $k => $v) {
if (curl_error($curl[$k]) == "") {
$text[$k] = (string) curl_multi_getcontent($curl[$k]);
}
curl_multi_remove_handle($handle, $curl[$k]);
curl_close($curl[$k]);
}
curl_multi_close($handle);
return $text;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
functioncurl_multi($urls){
if(!is_array($urls)orcount($urls)==0){
returnfalse;
}
$num=count($urls);
$curl=$curl2=$text=array();
$handle=curl_multi_init();
functioncreateCh($url){
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko');//設(shè)置頭部
curl_setopt($ch,CURLOPT_REFERER,$url);//設(shè)置來源
curl_setopt($ch,CURLOPT_ENCODING,"gzip");// 編碼壓縮
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);//是否采集301、302之后的頁面
curl_setopt($ch,CURLOPT_MAXREDIRS,5);//查找次數(shù),防止查找太深
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);// 對(duì)認(rèn)證證書來源的檢查
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);// 從證書中檢查SSL加密算法是否存在
curl_setopt($ch,CURLOPT_TIMEOUT,20);
curl_setopt($ch,CURLOPT_HEADER,0);//輸出頭部
return$ch;
}
foreach($urlsas$k=>$v){
$url=$urls[$k];
$curl[$k]=createCh($url);
curl_multi_add_handle($handle,$curl[$k]);
}
$active=null;
do{
$mrc=curl_multi_exec($handle,$active);
}while($mrc==CURLM_CALL_MULTI_PERFORM);
while($active&&$mrc==CURLM_OK){
if(curl_multi_select($handle)!=-1){
usleep(100);
}
do{
$mrc=curl_multi_exec($handle,$active);
}while($mrc==CURLM_CALL_MULTI_PERFORM);
}
foreach($curlas$k=>$v){
if(curl_error($curl[$k])==""){
$text[$k]=(string)curl_multi_getcontent($curl[$k]);
}
curl_multi_remove_handle($handle,$curl[$k]);
curl_close($curl[$k]);
}
curl_multi_close($handle);
return$text;
}
函數(shù)使用:
PHP
$urls=array('http://www.21863.cn',
'http://www.baidu.com',
'http://www.baidu.com',
'http://blog.21863.cn',
'http://www.baidu.com',
'http://www.baidu.com',
'http://www.baidu.com',
'http://www.baidu.com'
);
$res=curl_multi($urls);
print_r($res);
1
2
3
4
5
6
7
8
9
10
11
$urls=array('http://www.21863.cn',
'http://www.baidu.com',
'http://www.baidu.com',
'http://blog.21863.cn',
'http://www.baidu.com',
'http://www.baidu.com',
'http://www.baidu.com',
'http://www.baidu.com'
);
$res=curl_multi($urls);
print_r($res);
而這個(gè)多線程的采集函數(shù)怎么運(yùn)用到實(shí)際的項(xiàng)目中,這就很簡(jiǎn)單了吧!
總結(jié)
以上是生活随笔為你收集整理的php curl 防止采集,php多线程采集网页的解决办法 curl多线程采集的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php动态生成链接,PHP动态生成jav
- 下一篇: php如何防止超发,PHP+redis实