當前位置:
首頁 > 知識 > php中curl同時發送多個請求curl_multi函數集的用法

php中curl同時發送多個請求curl_multi函數集的用法

一、引言

這段時間比較忙,已經很久沒有寫博客了。今天我就來聊聊我關於curl_multi_*函數集的使用心得,關於http請求的問題。

當我們用戶php發起一個http請求的時候。我們會首先想到用什麼?沒錯,我們會創建curl來請求。當我們在一次執行中需要發起多個http請求呢。這簡單,對每一個URL發起一次url請求。請求玩第1個再請求第2個….這就完了?哪我們還說個啥。

官網鏈接: http://php.net/manual/zh/book.curl.php

二、多次簡單的curl請求弊端

圖1.串列請求與並行請求

我們舉個栗子。現在有三個http請求。每個請求耗時2s。如果按照簡單的curl請求(圖1-(1))。耗時6s.這是不能容忍的。如果請求的個數越多耗時約多。

有沒有一種方式來縮小查詢時間?能不能三個http請求同時執行(如圖1-(1))?有很多方法來解決這個問題,將耗時減少到2s。如:多進程、線程、事件循環、curl_multi_*等等。最簡單的方式就是通過curl_multi_*函數來完成。事實上curl_multi_*內部實現就是用的事件循環。

三、簡單的curl_multi_*運用

<?php

/**

*

* curl_multi_*簡單運用

*

* @author: rudy

* @date: 2016/07/12

*/

/**

* 根據url,postData獲取curl請求對象,這個比較簡單,可以看官方文檔

*/

function getCurlObject($url,$postData=array(),$header=array()){

$options = array();

$url = trim($url);

$options[CURLOPT_URL] = $url;

$options[CURLOPT_TIMEOUT] = 10;

$options[CURLOPT_USERAGENT] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36";

$options[CURLOPT_RETURNTRANSFER] = true;

// $options[CURLOPT_PROXY] = "127.0.0.1:8888";

foreach($header as $key=>$value){

$options[$key] =$value;

}

if(!empty($postData) && is_array($postData)){

$options[CURLOPT_POST] = true;

$options[CURLOPT_POSTFIELDS] = http_build_query($postData);

}

if(stripos($url,"https") === 0){

$options[CURLOPT_SSL_VERIFYPEER] = false;

}

$ch = curl_init();

curl_setopt_array($ch,$options);

return $ch;

}

// 創建三個待請求的url對象

$chList = array();

$chList[] = getCurlObject("https://www.baidu.com");

$chList[] = getCurlObject("http://www.jd.com");

$chList[] = getCurlObject("http://www.jianshu.com/");

// 創建多請求執行對象

$downloader = curl_multi_init();

// 將三個待請求對象放入下載器中

foreach ($chList as $ch){

curl_multi_add_handle($downloader,$ch);

}

// 輪詢

do {

while (($execrun = curl_multi_exec($downloader, $running)) == CURLM_CALL_MULTI_PERFORM) ;

if ($execrun != CURLM_OK) {

break;

}

// 一旦有一個請求完成,找出來,處理,因為curl底層是select,所以最大受限於1024

while ($done = curl_multi_info_read($downloader))

{

// 從請求中獲取信息、內容、錯誤

$info = curl_getinfo($done["handle"]);

$output = curl_multi_getcontent($done["handle"]);

$error = curl_error($done["handle"]);

// 將請求結果保存,我這裡是列印出來

print $output;

// print "一個請求下載完成!
";

// 把請求已經完成了得 curl handle 刪除

curl_multi_remove_handle($downloader, $done["handle"]);

}

// 當沒有數據的時候進行堵塞,把 CPU 使用權交出來,避免上面 do 死循環空跑數據導致 CPU 100%

if ($running) {

$rel = curl_multi_select($downloader, 1);

if($rel == -1){

usleep(1000);

}

}

if( $running == false){

break;

}

} while (true);

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

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

// 下載完畢,關閉下載器

curl_multi_close($downloader);

echo 「所有請求下載完成!」;

在該例子中,首先創建三個或多個要請求的url請求對象。通過curl_multi_*函數創建下載器。將請求寫入下載器中。最後輪詢。等待三個請求現在完成。做處理。

四、複雜的curl_multi_*運用

這就是curl_multi_*用法?too yong too simple!在上面的例子中。下載器$downloader中的請求是一開始就添加好了的。我們能不能動態的向下載器中添加請求。動態的從下載器中取出已經完成了的請求。想想。這是什麼?這不就是爬蟲的核心部分-動態下載器。如何動態的添加?我們可以用多進程通過IPC添加。我們可以通過協程通過隊列添加等待。

我這實現了一個通過協程+curl_multi_*的爬蟲框架。

Tspider: https://github.com/hirudy/Tspider 。

單進程可處理請求2000-5000/min。

php中curl同時發送多個請求curl_multi函數集的用法

打開今日頭條,查看更多精彩圖片
喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

「轉載」一個大數據屌絲的一天
基於elasticsearch6.2.3版本自定義插件開發遇到的問題總結

TAG:程序員小新人學習 |