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/

用PHP的curl实现并发请求远程文件(并发抓取远程网页)的更多相关文章

  1. linux 服务发布脚本升级,远程发布,指定拉取远程dev,test等分支代码

    1.本地发布脚本 publish.sh #!/bin/sh currentDay=`date +%Y%m%d` currentTime=`date +%Y%m%d%H%M%S` tomcat1=/da ...

  2. Linux远程自动输入密码抓取远程资源

    #!/usr/bin/expect -fset timeout 3000set sys_date [lindex $argv 0] #要抓取的文件日期spawn scp /data3/xiaorui/ ...

  3. Tomcat如何使用线程池处理远程并发请求

    Tomcat如何使用线程池处理远程并发请求 通过了解学习tomcat如何处理并发请求,了解到线程池,锁,队列,unsafe类,下面的主要代码来自 java-jre: sun.misc.Unsafe j ...

  4. 如何配置IIS处理多并发请求及存在的问题

    很多时候多线程能快速高效独立的计算数据,应用比较多. 但今天遇到的多进程下的问题更是让人觉得复杂 多进程下static变量都要失效,就目前的平台和产品static使用是很多的,各种session.ca ...

  5. 使用CURL下载远程文件保存到服务器

    比如微信公众平台开发,下载用户的头像到服务器上: /** * 使用CURL获取远程文件保存到服务器 *@param $image=$oJSON->headimgurl; 获取到的微信返回的头像U ...

  6. Rolling cURL: PHP并发最佳实践

    Rolling cURL: PHP并发最佳实践 在实际项目或者自己编写小工具(比如新闻聚合,商品价格监控,比价)的过程中, 通常需要从第3方网站或者API接口获取数据, 在需要处理1个URL队列时, ...

  7. PHP学习笔记,curl,file_get_content,include和fopen四种方法获取远程文件速度测试.

    这几天在做抓取.发现用PHP的file_get_contents函数来获取远程文件的过程中总是出现失败,并且效率很低下.所以就做了个测试的demo来测试下PHP中各种方法获取文件的速度. 程序里面使用 ...

  8. php curl模拟post请求提交数据样例总结

    在php中要模拟post请求数据提交我们会使用到curl函数,以下我来给大家举几个curl模拟post请求提交数据样例有须要的朋友可參考參考.注意:curl函数在php中默认是不被支持的,假设须要使用 ...

  9. java中如何模拟真正的同时并发请求?

    有时需要测试一下某个功能的并发性能,又不要想借助于其他工具,索性就自己的开发语言,来一个并发请求就最方便了. java中模拟并发请求,自然是很方便的,只要多开几个线程,发起请求就好了.但是,这种请求, ...

随机推荐

  1. 牛刀小试MySQL--innodb_flush_log_at_trx_commit小结

    参数名:innodb_flush_log_at_trx_commit 参数值: 0 事务提交的时候,不会去刷日志缓存区,也不会立马写入至日志文件中.这种设置最危险.如果数据库挂了且运气不好,数据库的最 ...

  2. 学会4种备份MySQL数据库(基本备份方面没问题了)

    前言 我们试着想一想, 在生产环境中什么最重要?如果我们服务器的硬件坏了可以维修或者换新, 软件问题可以修复或重新安装, 但是如果数据没了呢?这可能是最恐怖的事情了吧, 我感觉在生产环境中应该没有什么 ...

  3. 【Java基础】15、负数的二进制表示方法

    在计算机中,负数以其正值的补码形式表达. 什么叫补码呢?这得从原码,反码说起. 原码:一个整数,按照绝对值大小转换成的二进制数,称为原码. 比如 00000000 00000000 00000000 ...

  4. 在WindowsPhone开发中使用MVVM设计模式

    相信.NET程序员多多少少都听说过MVVM的设计模式,对于一个大一点的项目来说,使用这种设计模式无疑是一种不错的选择, 它提高了程序的可维护性,降低了耦合度,可以实现代码的重用,方便独立开发和进行测试 ...

  5. Mybatis逆向工程生成po、mapper接口、mapper.xml

    Mybatis逆向工程生成po.mapper接口.mapper.xml 一.新建一个maven工程 请查看我的另一篇博客:<使用idea创建一个maven工程> 二.引入所需依赖 需要my ...

  6. CoreCRM 开发实录 —— 基于 AntDesign 的新 UI

    上一篇说到,因为有新朋友加入,对前端开发有了新的要求.原来基于 Bootstrap 的 UI 就不要了.在网上(其实是 GitHub 上)逛了几圈,最后使用了 antd-admin 这个框架做为基础模 ...

  7. windows 2012 r2企业版没有界面

    windows 2012 R2系统进去以后只有CMD命令窗口,没有图形化界面,除了cmd其余的全部是黑的.在网上搜了很多,都是大同小异的解决方法,但根本解决不了.今天再这里分享的这个方法很简单,不用重 ...

  8. CloudSim源代码学习——任务单元(Cloudlet)

    /* * Title: CloudSim Toolkit * Description: CloudSim (Cloud Simulation) Toolkit for Modeling and Sim ...

  9. 《Inside C#》笔记(六) 属性、数组、索引器

    一 属性 a) 属性可用于隐藏类的内部成员,对外提供可控的存取接口.属性相当于有些语言的getter.setter方法,只是使用起来更加方便一点,而且查看对应的IL码可以看到,属性的本质也确实是方法. ...

  10. 项目开发常见字符串处理模型-strstr-while/dowhile模型

    strstr-whiledowhile模型用于在母字符串中查找符合特征的子字符串. c语言库提供了strstr函数,strstr函数用于判断母字符串中是否包含子字符串,包含的话返回子字符串的位置指针, ...