1. 소개
이 기간 동안 너무 바빠서 오랫동안 블로그를 하지 못했습니다. 오늘은 컬_멀티_* 함수 세트 사용 경험과 http 요청 문제에 대해 이야기하겠습니다.
사용자 PHP가 http 요청을 시작할 때. 가장 먼저 무엇을 사용할 생각을 할까요? 맞습니다. 요청에 따라 컬을 생성하겠습니다. 한 번의 실행으로 여러 http 요청을 시작해야 한다면 어떻게 될까요? 이는 간단합니다. 각 URL에 대해 URL을 요청하면 됩니다. 1편 요청하고 2편 요청하고... 이게 끝인가요? 또 무슨 말을 할 수 있나요?
공식 홈페이지 링크: http://php.net/manual/zh/book.curl.php
2. 단순 컬 요청의 단점
밤을 드리자. 이제 세 개의 http 요청이 있습니다. 각 요청에는 2초가 걸립니다. 간단한 컬 요청을 따르는 경우(그림 1-(1)). 6초가 걸렸습니다. 요청이 많을수록 시간이 더 오래 걸립니다.
쿼리 시간을 줄이는 방법이 있나요? 세 개의 http 요청을 동시에 실행할 수 있습니까(그림 1-(1))? 이 문제를 해결하고 시간 소모를 2초로 줄이는 방법은 여러 가지가 있습니다. 예: 다중 프로세스, 스레드, 이벤트 루프, 컬_멀티_* 등 가장 간단한 방법은 컬_멀티_* 함수를 사용하는 것입니다. 실제로, 컬_멀티_*의 내부 구현은 이벤트 루프를 사용합니다.
3. 단순 컬_멀티_* 애플리케이션
<code><span><?php</span><span>/** * * curl_multi_*简单运用 * *<span> @author</span>: rudy *<span> @date</span>: 2016/07/12 */</span><span>/** * 根据url,postData获取curl请求对象,这个比较简单,可以看官方文档 */</span><span><span>function</span><span>getCurlObject</span><span>(<span>$url</span>,<span>$postData</span>=array<span>()</span>,<span>$header</span>=array<span>()</span>)</span>{</span><span>$options</span> = <span>array</span>(); <span>$url</span> = trim(<span>$url</span>); <span>$options</span>[CURLOPT_URL] = <span>$url</span>; <span>$options</span>[CURLOPT_TIMEOUT] = <span>10</span>; <span>$options</span>[CURLOPT_USERAGENT] = <span>'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'</span>; <span>$options</span>[CURLOPT_RETURNTRANSFER] = <span>true</span>; <span>// $options[CURLOPT_PROXY] = '127.0.0.1:8888';</span><span>foreach</span>(<span>$header</span><span>as</span><span>$key</span>=><span>$value</span>){ <span>$options</span>[<span>$key</span>] =<span>$value</span>; } <span>if</span>(!<span>empty</span>(<span>$postData</span>) && is_array(<span>$postData</span>)){ <span>$options</span>[CURLOPT_POST] = <span>true</span>; <span>$options</span>[CURLOPT_POSTFIELDS] = http_build_query(<span>$postData</span>); } <span>if</span>(stripos(<span>$url</span>,<span>'https'</span>) === <span>0</span>){ <span>$options</span>[CURLOPT_SSL_VERIFYPEER] = <span>false</span>; } <span>$ch</span> = curl_init(); curl_setopt_array(<span>$ch</span>,<span>$options</span>); <span>return</span><span>$ch</span>; } <span>// 创建三个待请求的url对象</span><span>$chList</span> = <span>array</span>(); <span>$chList</span>[] = getCurlObject(<span>'https://www.baidu.com'</span>); <span>$chList</span>[] = getCurlObject(<span>'http://www.jd.com'</span>); <span>$chList</span>[] = getCurlObject(<span>'http://www.jianshu.com/'</span>); <span>// 创建多请求执行对象</span><span>$downloader</span> = curl_multi_init(); <span>// 将三个待请求对象放入下载器中</span><span>foreach</span> (<span>$chList</span><span>as</span><span>$ch</span>){ curl_multi_add_handle(<span>$downloader</span>,<span>$ch</span>); } <span>// 轮询</span><span>do</span> { <span>while</span> ((<span>$execrun</span> = curl_multi_exec(<span>$downloader</span>, <span>$running</span>)) == CURLM_CALL_MULTI_PERFORM) ; <span>if</span> (<span>$execrun</span> != CURLM_OK) { <span>break</span>; } <span>// 一旦有一个请求完成,找出来,处理,因为curl底层是select,所以最大受限于1024</span><span>while</span> (<span>$done</span> = curl_multi_info_read(<span>$downloader</span>)) { <span>// 从请求中获取信息、内容、错误</span><span>$info</span> = curl_getinfo(<span>$done</span>[<span>'handle'</span>]); <span>$output</span> = curl_multi_getcontent(<span>$done</span>[<span>'handle'</span>]); <span>$error</span> = curl_error(<span>$done</span>[<span>'handle'</span>]); <span>// 将请求结果保存,我这里是打印出来</span><span>print</span><span>$output</span>; <span>// print "一个请求下载完成!\n";</span><span>// 把请求已经完成了得 curl handle 删除</span> curl_multi_remove_handle(<span>$downloader</span>, <span>$done</span>[<span>'handle'</span>]); } <span>// 当没有数据的时候进行堵塞,把 CPU 使用权交出来,避免上面 do 死循环空跑数据导致 CPU 100%</span><span>if</span> (<span>$running</span>) { <span>$rel</span> = curl_multi_select(<span>$downloader</span>, <span>1</span>); <span>if</span>(<span>$rel</span> == -<span>1</span>){ usleep(<span>1000</span>); } } <span>if</span>( <span>$running</span> == <span>false</span>){ <span>break</span>; } } <span>while</span> (<span>true</span>); <span>// 下载完毕,关闭下载器</span> curl_multi_close(<span>$downloader</span>); <span>echo</span><span>"所有请求下载完成!"</span>;</span></code>
이 예에서는 먼저 요청할 URL 요청 개체를 3개 이상 만듭니다. 컬_멀티_* 함수를 통해 다운로더를 생성합니다. 다운로더에 요청을 작성합니다. 마지막 여론조사. 이제 세 가지 요청이 완료되기를 기다리고 있습니다. 처리를 합니다.
4. 복잡한 컬_멀티_* 사용법
이렇게 컬_멀티_*를 사용하는 건가요? 너무 용, 너무 단순해요! 위의 예에서. 다운로더 $downloader의 요청은 처음부터 추가됩니다. 다운로더에 요청을 동적으로 추가할 수 있습니까? 다운로더에서 완료된 요청을 동적으로 검색합니다. 생각해 보세요. 이건 뭐죠? 이것이 크롤러의 핵심 부분인 동적 다운로더가 아닌가? 동적으로 추가하는 방법은 무엇입니까? 다중 프로세스를 사용하여 IPC를 통해 추가할 수 있습니다. 코루틴을 통해 대기열을 통해 대기를 추가할 수 있습니다.
').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i ').text(i)); }; $numbering.fadeIn(1700); }); });코루틴 cur_multi_*를 통해 크롤러 프레임워크를 구현했습니다.
Tspider: https://github.com/hirudy/Tspider.
단일 프로세스는 2000-5000/분의 요청을 처리할 수 있습니다.
이상은 관련 내용을 포함하여 PHP에 설정된 컬_멀티(curl_multi) 함수의 사용법을 소개하고 있으며, PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.