zoukankan      html  css  js  c++  java
  • 用PHP的curl实现并发请求远程文件(并发抓取远程网页)

    PHP的curl功能确实强大了。里面有个curl_multi_init功能,就是批量处理任务。可以利用此,实现多进程同步抓取多条记录,优化普通的网页抓取程序。

    一个简单的抓取函数:

    function http_get_multi($urls){
        $count = count($urls);
        $data = [];
        $chs = [];
    
        // 创建批处理cURL句柄
        $mh = curl_multi_init();
    
        // 创建cURL资源
        for($i = 0; $i < $count; $i ++){
            $chs[ $i ] = curl_init();
            // 设置URL和相应的选项
            curl_setopt($chs[ $i ], CURLOPT_RETURNTRANSFER, 1); // return don't print
            curl_setopt($chs[ $i ], CURLOPT_URL, $urls[$i]);
            curl_setopt($chs[ $i ], CURLOPT_HEADER, 0);
    
            curl_multi_add_handle($mh, $chs[ $i ]);
        }
        // 增加句柄
        // for($i = 0; $i < $count; $i ++){
            // curl_multi_add_handle($mh, $chs[ $i ]);
        // }
    
        // 执行批处理句柄
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($active > 0);
    
        while ($active and $mrc == CURLM_OK) {
            if (curl_multi_select($mh) != -1) {
                do {
                    $mrc = curl_multi_exec($mh, $active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
            }
        }
    
        for($i = 0; $i < $count; $i ++){
            $content  = curl_multi_getcontent($chs[ $i ]);
            $data[ $i ] = ( curl_errno($chs[ $i ]) == 0 ) ? $content : false;
        }
        // 关闭全部句柄
        for($i = 0; $i < $count; $i ++){
            curl_multi_remove_handle($mh, $chs[ $i ]);
        }
        curl_multi_close($mh);
        return $data;
    }

    下面的调用测试(get()函数如这里: http://www.cnblogs.com/whatmiss/p/7114954.html):

    //弄很多个网页的url
    $url
    = [ 'http://www.baidu.com', 'http://www.163.com', 'http://www.sina.com.cn', 'http://www.qq.com', 'http://www.sohu.com', 'http://www.douban.com', 'http://www.cnblogs.com', 'http://www.taobao.com', 'http://www.php.net', ]; $urls = []; for($i = 0; $i < 10; $i ++){ foreach($url as $r) $urls[] = $r . '/?v=' . rand(); }

    //并发请求
    $datas = http_get_multi($urls); foreach($datas as $key => $data){ file_put_contents('log/multi_' . $key . '.txt', $data); // 记录一下请求结果。记得创建一个log文件夹 } $t2 = microtime(true); echo $t2 - $t1; echo '<br />';

    //同步请求, get()函数如这里: http://www.cnblogs.com/whatmiss/p/7114954.html
    $t1 = microtime(true); foreach($urls as $key => $url){ file_put_contents('log/get_' . $key . '.txt', get($url)); // 记录一下请求结果。记得创建一个log文件夹 } $t2 = microtime(true); echo $t2 - $t1;

    测试结果,很明显的差距,而且随着数据量越大,会呈指数级的拉大差距:

    2.4481401443481
    21.68923997879
    
    8.925509929657
    24.73141503334
    
    3.243185043335
    23.384337902069
    
    3.2841880321503
    24.754415035248
     
    3.2091829776764
    29.068662881851

    参考,感谢原作者:

    http://php.net/manual/zh/function.curl-multi-init.php

    http://www.tuicool.com/articles/auiEBb

    http://blog.csdn.net/liylboy/article/details/39669963 此文写了可能超时的问题

    另,这里有一篇文章说,多线程并不会更快,甚至还稍慢一点点,我觉得很奇怪,怎么会有这样的结果:

    http://www.webkaka.com/tutorial/php/2013/102843/

  • 相关阅读:
    垃圾回收的可触及性
    常用的垃圾回收算法
    石子归并(区间dp 模板)
    D. Zero Quantity Maximization ( Codeforces Round #544 (Div. 3) )
    Parity game(带权并查集+离散化)
    Supermarket(贪心/并查集)
    D. Nested Segments(树状数组、离散化)
    dijkstra,belllman-ford,spfa最短路算法
    重载符
    Electrification Plan 最小生成树(prim+krusl+堆优化prim)
  • 原文地址:https://www.cnblogs.com/whatmiss/p/7118054.html
Copyright © 2011-2022 走看看