php结合curl实现多线程抓取


Posted in PHP onJuly 09, 2015

php结合curl实现多线程抓取

<?php
/*
curl 多线程抓取
*/
 /** 
   * curl 多线程 
   * 
   * @param array $array 并行网址 
   * @param int $timeout 超时时间
   * @return array 
   */ 
 function Curl_http($array,$timeout){
 $res = array();
 $mh = curl_multi_init();//创建多个curl语柄
 $startime = getmicrotime();
 foreach($array as $k=>$url){
  $conn[$k]=curl_init($url);

    curl_setopt($conn[$k], CURLOPT_TIMEOUT, $timeout);//设置超时时间
    curl_setopt($conn[$k], CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
    curl_setopt($conn[$k], CURLOPT_MAXREDIRS, 7);//HTTp定向级别
    curl_setopt($conn[$k], CURLOPT_HEADER, 0);//这里不要header,加块效率
    curl_setopt($conn[$k], CURLOPT_FOLLOWLOCATION, 1); // 302 redirect
    curl_setopt($conn[$k],CURLOPT_RETURNTRANSFER,1);
    curl_multi_add_handle ($mh,$conn[$k]);
 }
 //防止死循环耗死cpu 这段是根据网上的写法
 do {
  $mrc = curl_multi_exec($mh,$active);//当无数据,active=true
 } while ($mrc == CURLM_CALL_MULTI_PERFORM);//当正在接受数据时
 while ($active and $mrc == CURLM_OK) {//当无数据时或请求暂停时,active=true
  if (curl_multi_select($mh) != -1) {
  do {
   $mrc = curl_multi_exec($mh, $active);
  } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  }
 }

 foreach ($array as $k => $url) {
   curl_error($conn[$k]);
    $res[$k]=curl_multi_getcontent($conn[$k]);//获得返回信息
    $header[$k]=curl_getinfo($conn[$k]);//返回头信息
    curl_close($conn[$k]);//关闭语柄
    curl_multi_remove_handle($mh , $conn[$k]);  //释放资源 
 }

 curl_multi_close($mh);
 $endtime = getmicrotime();
 $diff_time = $endtime - $startime;

 return array('diff_time'=>$diff_time,
   'return'=>$res,
   'header'=>$header 
   );

 }
 //计算当前时间
 function getmicrotime() {
   list($usec, $sec) = explode(" ",microtime());
   return ((float)$usec + (float)$sec);
 }

 //测试一下,curl 三个网址
 $array = array(
  "http://www.weibo.com/",
  "http://www.renren.com/",
  "http://www.qq.com/"
  );
 $data = Curl_http($array,'10');//调用
 var_dump($data);//输出
//如果POST的数据大于1024字节,curl并不会直接就发起POST请求
//发送请求时,header中包含一个空的Expect。curl_setopt($ch, CURLOPT_HTTPHEADER, array("Expect:"));
?>

我们再来看几个例子

(1)下面这段代码是实现抓取多个URL,然后将抓取的URL的页面代码写入指定的文件

$urls = array(
'https://3water.com/',
'http://www.google.com/',
'http://www.example.com/'
); // 设置要抓取的页面URL
$save_to='/test.txt'; // 把抓取的代码写入该文件
$st = fopen($save_to,"a");
$mh = curl_multi_init();
foreach ($urls as $i => $url) {
$conn[$i] = curl_init($url);
curl_setopt($conn[$i], CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");
curl_setopt($conn[$i], CURLOPT_HEADER ,0);
curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT,60);
curl_setopt($conn[$i], CURLOPT_FILE,$st); // 将爬取的代码写入文件
curl_multi_add_handle ($mh,$conn[$i]);
} // 初始化
do {
curl_multi_exec($mh,$active);
} while ($active); // 执行
foreach ($urls as $i => $url) {
curl_multi_remove_handle($mh,$conn[$i]);
curl_close($conn[$i]);
} // 结束清理
curl_multi_close($mh);
fclose($st);

(2)下面这段代码和上面差不多意思,只不过这个地方是将获得的代码先放入变量,然后再将获取到的内容写入指定的文件

$urls = array(
'https://3water.com/',
'http://www.google.com/',
'http://www.example.com/'
);
$save_to='/test.txt'; // 把抓取的代码写入该文件
$st = fopen($save_to,"a");
$mh = curl_multi_init();
foreach ($urls as $i => $url) {
$conn[$i] = curl_init($url);
curl_setopt($conn[$i], CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");
curl_setopt($conn[$i], CURLOPT_HEADER ,0);
curl_setopt($conn[$i], CURLOPT_CONNECTTIMEOUT,60);
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,true); // 不将爬取代码写到浏览器,而是转化为字符串
curl_multi_add_handle ($mh,$conn[$i]);
}
do {
curl_multi_exec($mh,$active);
} while ($active);
foreach ($urls as $i => $url) {
$data = curl_multi_getcontent($conn[$i]); // 获得爬取的代码字符串
fwrite($st,$data); // 将字符串写入文件
} // 获得数据变量,并写入文件
foreach ($urls as $i => $url) {
curl_multi_remove_handle($mh,$conn[$i]);
curl_close($conn[$i]);
}
curl_multi_close($mh);
fclose($st);

(3)下面这段代码实现的是利用 PHP 的 Curl Functions 实现并发多线程下载文件

$urls=array(
 'https://3water.com/5w.zip',
 'https://3water.com/5w.zip',
 'https://3water.com/5w.zip'
);
$save_to='./home/';
$mh=curl_multi_init();
foreach($urls as $i=>$url){
 $g=$save_to.basename($url);
 if(!is_file($g)){
   $conn[$i]=curl_init($url);
   $fp[$i]=fopen($g,"w");
   curl_setopt($conn[$i],CURLOPT_USERAGENT,"Mozilla/4.0(compatible; MSIE 7.0; Windows NT 6.0)");
   curl_setopt($conn[$i],CURLOPT_FILE,$fp[$i]);
   curl_setopt($conn[$i],CURLOPT_HEADER ,0);
   curl_setopt($conn[$i],CURLOPT_CONNECTTIMEOUT,60);
   curl_multi_add_handle($mh,$conn[$i]);
 }
}
do{
 $n=curl_multi_exec($mh,$active);
}while($active);
foreach($urls as $i=>$url){
 curl_multi_remove_handle($mh,$conn[$i]);
 curl_close($conn[$i]);
 fclose($fp[$i]);
}
curl_multi_close($mh);$urls=array(
 'https://3water.com/5w.zip',
 'https://3water.com/5w.zip',
 'https://3water.com/5w.zip'
);
$save_to='./home/';
$mh=curl_multi_init();
foreach($urls as $i=>$url){
 $g=$save_to.basename($url);
 if(!is_file($g)){
   $conn[$i]=curl_init($url);
   $fp[$i]=fopen($g,"w");
   curl_setopt($conn[$i],CURLOPT_USERAGENT,"Mozilla/4.0(compatible; MSIE 7.0; Windows NT 6.0)");
   curl_setopt($conn[$i],CURLOPT_FILE,$fp[$i]);
   curl_setopt($conn[$i],CURLOPT_HEADER ,0);
   curl_setopt($conn[$i],CURLOPT_CONNECTTIMEOUT,60);
   curl_multi_add_handle($mh,$conn[$i]);
 }
}
do{
 $n=curl_multi_exec($mh,$active);
}while($active);
foreach($urls as $i=>$url){
 curl_multi_remove_handle($mh,$conn[$i]);
 curl_close($conn[$i]);
 fclose($fp[$i]);
}
curl_multi_close($mh);

以上所述就是本文的全部内容了,希望大家能够喜欢。

PHP 相关文章推荐
php array_map()数组函数使用说明
Jul 12 PHP
深入解析php之sphinx
May 15 PHP
yii框架配置默认controller和action示例
Apr 30 PHP
codeigniter数据库操作函数汇总
Jun 12 PHP
PHP实现定时执行任务的方法
Oct 05 PHP
分享PHP计算两个日期相差天数的代码
Dec 23 PHP
PHP引用的调用方法分析
Apr 25 PHP
php版微信数据统计接口用法示例
Oct 12 PHP
ThinkPHP5 验证器的具体使用
May 31 PHP
PHP自动载入类文件函数__autoload的使用方法
Mar 25 PHP
Yii框架响应组件用法实例分析
Sep 04 PHP
tp5 实现列表数据根据状态排序
Oct 18 PHP
php基本函数汇总
Jul 09 #PHP
php+curl 发送图片处理代码分享
Jul 09 #PHP
在Debian系统下配置LNMP的教程
Jul 09 #PHP
PHP+Mysql基于事务处理实现转账功能的方法
Jul 08 #PHP
php将html转成wml的WAP标记语言实例
Jul 08 #PHP
php实现数组中索引关联数据转换成json对象的方法
Jul 08 #PHP
PHP使用pear自带的mail类库发邮件的方法
Jul 08 #PHP
You might like
PHP中str_replace函数使用小结
2008/10/11 PHP
PHP is_dir() 判断给定文件名是否是一个目录
2010/05/10 PHP
php接口和抽象类使用示例详解
2014/03/02 PHP
用js自动判断浏览器分辨率的代码
2007/01/28 Javascript
从盛大通行证上摘下来的身份证验证js代码
2011/01/11 Javascript
JavaScript高级程序设计 阅读笔记(十三) js定义类或对象
2012/08/14 Javascript
鼠标拖动实现DIV排序示例代码
2013/10/14 Javascript
深入理解JavaScript系列(46):代码复用模式(推荐篇)详解
2015/03/04 Javascript
javascript实现捕捉键盘上按下的键
2015/05/05 Javascript
在JavaScript的AngularJS库中进行单元测试的方法
2015/06/23 Javascript
JS实现支持多选的遍历下拉列表代码
2015/08/20 Javascript
JS组件Bootstrap Table表格行拖拽效果实现代码
2020/08/27 Javascript
JS实现的汉字与Unicode码相互转化功能分析
2018/05/25 Javascript
详解在React.js中使用PureComponent的重要性和使用方式
2018/07/10 Javascript
详解用vue2.x版本+adminLTE开源框架搭建后台应用模版
2019/03/15 Javascript
JS中的算法与数据结构之列表(List)实例详解
2019/08/16 Javascript
webpack + vue 打包生成公共配置文件(域名) 方便动态修改
2019/08/29 Javascript
Javascript和jquery在selenium的使用过程
2019/10/31 jQuery
React.js组件实现拖拽排序组件功能过程解析
2020/04/27 Javascript
JavaScript代码模拟鼠标自动点击事件示例
2020/08/07 Javascript
pyv8学习python和javascript变量进行交互
2013/12/04 Python
python实现socket客户端和服务端简单示例
2014/02/24 Python
Python使用BeautifulSoup库解析HTML基本使用教程
2016/03/31 Python
python 捕获 shell/bash 脚本的输出结果实例
2017/01/04 Python
Python 私有函数的实例详解
2017/09/11 Python
Django处理多用户类型的方法介绍
2019/05/18 Python
对pyqt5之menu和action的使用详解
2019/06/20 Python
PyQt5实现简易电子词典
2019/06/25 Python
Python函数参数类型及排序原理总结
2019/12/19 Python
pytorch 实现L2和L1正则化regularization的操作
2021/03/03 Python
美国购买肉、鸭、家禽、鹅肝和熟食网站:D’Artagnan
2018/11/13 全球购物
党员批评与自我批评范文
2014/09/23 职场文书
欢送会主持词
2015/07/01 职场文书
XX部保密工作制度范本
2019/08/27 职场文书
go select编译期的优化处理逻辑使用场景分析
2021/06/28 Golang
MySQL对数据表已有表进行分区表的实现
2021/11/01 MySQL