php多线程抓取信息测试例子

PHP 5.3 以上版本,使用pthreads PHP扩展,可以使PHP真正地支持多线程。多线程在处理重复性的循环任务,能够大大缩短程序执行时间。
PHP扩展下载:https://github.com/krakjoe/pthreads
PHP手册文档:http://php.net/manual/zh/book.pthreads.php
1、扩展的编译安装(Linux),编辑参数 --enable-maintainer-zts 是必选项:
cd /Data/tgz/php-5.3.8
./configure --prefix=/Data/apps/php --with-config-file-path=/Data/apps/php/etc --with-mysql=/Data/apps/mysql --with-mysqli=/Data/apps/mysql/bin/mysql_config --with-iconv-dir --with-freetype-dir=/Data/apps/libs --with-jpeg-dir=/Data/apps/libs --with-png-dir=/Data/apps/libs --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-fpm --enable-mbstring --with-mcrypt=/Data/apps/libs --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --enable-opcache --with-pdo-mysql --enable-maintainer-zts
make clean
make
make install unzip pthreads-master.zip
cd pthreads-master
/Data/apps/php/bin/phpize
./configure --with-php-config=/Data/apps/php/bin/php-config
make
make install
添加扩展: vi /Data/apps/php/etc/php.ini
extension = "pthreads.so"
一段PHP多线程、与For循环,抓取百度搜索页面的PHP代码示例:
代码如下 复制代码
<?php
class test_thread_run extends Thread
{
public $url;
public $data; public function __construct($url)
{
$this->url = $url;
} public function run()
{
if(($url = $this->url))
{
$this->data = model_http_curl_get($url);
}
}
} function model_thread_result_get($urls_array)
{
foreach ($urls_array as $key => $value)
{
$thread_array[$key] = new test_thread_run($value["url"]);
$thread_array[$key]->start();
} foreach ($thread_array as $thread_array_key => $thread_array_value)
{
while($thread_array[$thread_array_key]->isRunning())
{
usleep(10);
}
if($thread_array[$thread_array_key]->join())
{
$variable_data[$thread_array_key] = $thread_array[$thread_array_key]->data;
}
}
return $variable_data;
} function model_http_curl_get($url,$userAgent="")
{
$userAgent = $userAgent ? $userAgent : 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2)';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, 5);
curl_setopt($curl, CURLOPT_USERAGENT, $userAgent);
$result = curl_exec($curl);
curl_close($curl);
return $result;
} for ($i=0; $i < 100; $i++)
{
$urls_array[] = array("name" => "baidu", "url" => "http://www.baidu.com/s?wd=".mt_rand(10000,20000));
} $t = microtime(true);
$result = model_thread_result_get($urls_array);
$e = microtime(true);
echo "多线程:".($e-$t)."n"; $t = microtime(true);
foreach ($urls_array as $key => $value)
{
$result_new[$key] = model_http_curl_get($value["url"]);
}
$e = microtime(true);
echo "For循环:".($e-$t)."n";
?>
例子,采集数据 代码如下 复制代码
<?php
$urls = array(
'http://www.111cn.net/',
'http://www.sohu.com/',
'http://www.163.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);
?> 出于对算法对于系统的影响的好奇,决定实验性的在实际生产环境中研究一下算法对系统效率的影响。二分法最重要的是对有序数据的查询定位,例如手机号码就是一个很贴切的有序排列的数据例子。
如果数据量很小,例如只有10条有序数据,要查询其中的第9条数据,轮询查询需要查询9次确定结果,二分法查询次数为3次(分别是匹配第5、8、9条记录)即可确定结果。数据量越大,二分法所带来的效率就是程2的阶乘递增,可以大大提升服务器的运行效率、提升用户等待时间、节省服务器资源。
实验环境:LAMP
实验数据:国内手机号码归属地。手机号码前7位代表一个号段,生成从1300000到1590000之间的所有号段按从小到大排列,大约30万条数据。
传统查询:对于任意手机号码,截取前7位,从数据库中第一条记录开始循环向下匹配,如果对照,则返回查询结果。
代码如下 复制代码
flock($fp,LOCK_SH);
$note = fread($fp,filesize('./data.php')); //读取数据
fclose($fp);
$note = explode("n",$note);
array_pop($note);
array_shift($note);
$num = count($note);
$_data = '';
//循环查询开始
for($i=1;$i<$num;$i++){
$row = explode(" ",$note[$i]);
if($m == $row[0]){
$_data = $row;
break;
}
}
实测结果:最快0.03512秒、最慢0.63043秒、平均查询用时约为0.4秒。
二分法查询:对于任意手机号码,截取前7位。首先匹配数据库中最中间的第100000条数据,根据二分法原则,若匹配结果比中间值大,重新选择第二次匹配第100000到200000的中间值----第150000条数据。以此类推,直到查询到最后一位正确的值返回结果。那么每次的查询次数小于或等于17次。
代码如下 复制代码
flock($fp,LOCK_SH);
$note = fread($fp,filesize('./data.php')); //读取数据
fclose($fp);
$note = explode("n",$note);
array_pop($note);
array_shift($note);
$num = count($note); //统计数据库总记录数
$_data = '';
$low = 0; //二分法两端点变量
$hight = $num;
while($m < 1599999){
$num = ceil(($hight + $low)/2);
$row = explode(" ",$note[$num]);
if ($m == $row[0]){
return $_data = $row;
break;
}else{
$m >= $row[0] ? $low = $num : $hight = $num;
}
}
实测结果:每次查询都在0.034—0.035之间。
结论:本试验可以看出,二分法数据查询效率比传统效率快10倍以上。本实验数据只有30万条,在普通的应用性数据查询时,数据量越大,越能显示出二分法的优越性(理论上讲,上千万的数据查询次数不超过30次便可准确定位),在更大量的数据的时候,查询效率或许能真的给人直观的反应。 效果如下
提交
代码如下 复制代码
index.php文件
php结合jquery异步上传图片(ajaxSubmit),以下为提交页面代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax异步上传图片</title>
<script src="js/jquery-1.4.2.js" language="JavaScript" type="text/javascript"></script>
<script src="js/jquery.form.js" language="JavaScript" type="text/javascript"></script>
<script type="text/javascript">
function sky_upfiles(){
var messtxt;
$("#sky_upform").ajaxSubmit({
//dataType:'script',
type:'post',
url: "doupfiles.php",
beforeSubmit: function(){
$("#sky_txt").html("图片上传中...");
},
success: function(data){
if(data=="1"){
messtxt = "上传成功!";
}else if(data=="-1"){
messtxt = "文件超过规定大小!";
}else if(data=="-2"){
messtxt = "文件类型不符!";
}else if(data=="-3"){
messtxt = "移动文件出错!";
}else{
messtxt = "未知错误!";
}
$("#sky_txt").html(messtxt);
//$("#sky_txt").append(data);
},
resetForm: false,
clearForm: false
});
//$("#upimgform").submit();
}
</script>
</head>
<body>
<br />
<fieldset style="width:97%">
<legend>上传文件</legend>
<form enctype="multipart/form-data" id="sky_upform" name="sky_upform" action="" method="post">
<table width="100%" border="0" align="center" cellpadding="3" cellspacing="0">
<tr>
<td width="100" align="right" class="f-12"></td>
<td class="f-12" align="left">
<input name="upfile" id="upfile" maxlength="20" size="40" type="file" value="" /><input name="upmit" type="button" id="upmit" value="上传" onclick="sky_upfiles()"/>
<font color="red" id="sky_txt"></font></td>
</tr>
</form> </body>
</html>
doupfiles.php文件
代码如下 复制代码
<?php
/*
* 1:成功上传
*-1:文件超过规定大小
*-2:文件类型不符
*-3:移动文件出错
*/
if(is_uploaded_file($_FILES['upfile']['tmp_name'])){
$photo_types=array('image/jpg', 'image/jpeg','image/png','image/pjpeg','image/gif','image/bmp','image/x-png');//定义上传格式
$max_size=700000; //上传照片大小限制,默认700k
$photo_folder="upload/".date("Y")."/".date("m")."/".date("d")."/"; //上传照片路径
///////////////////////////////////////////////////开始处理上传
if(!file_exists($photo_folder))//检查照片目录是否存在
{
mkdir($photo_folder, 0777, true); //mkdir("temp/sub, 0777, true);
}
$upfile=$_FILES['upfile'];
$name=$upfile['name'];
$type=$upfile['type'];
$size=$upfile['size'];
$tmp_name=$upfile['tmp_name'];
$file = $_FILES["upfile"];
$photo_name=$file["tmp_name"];
//echo $photo_name;
$photo_size = getimagesize($photo_name);
if($max_size < $file["size"])//检查文件大小
echo "-1"; //echo "<script>alert('对不起,文件超过规定大小!');history.go(-1);</script>";
if(!in_array($file["type"], $photo_types))//检查文件类型
echo "-2"; //echo "<script>alert('对不起,文件类型不符!');history.go(-1);</script>";
if(!file_exists($photo_folder))//照片目录
mkdir($photo_folder);
$pinfo=pathinfo($file["name"]);
$photo_type=$pinfo['extension'];//上传文件扩展名
$photo_server_folder = $photo_folder.time().".".$photo_type;//以当前时间和7位随机数作为文件名,这里是上传的完整路径 if(!move_uploaded_file ($photo_name, $photo_server_folder))
{
echo "-3"; //echo "移动文件出错";
exit;
}
$pinfo=pathinfo($photo_server_folder);
$fname=$pinfo['basename'];
echo "1"; //echo " 已经成功上传:".$photo_server_folder."<br />"; }
?>
最后把完整的php+jquery Ajax异步上传图片(ajaxSubmit)实例源码下载地址

  

最新文章

  1. 第一章 简单工厂模式 及 UML中类图的表示方法
  2. .NET基础架构方法—DataTableToList通用方法
  3. 【BZOJ 3242】【UOJ #126】【CodeVS 3047】【NOI 2013】快餐店
  4. 深度剖析:如何实现一个 Virtual DOM 算法
  5. Android Intent (可通过URL启动 Activity)
  6. java 子类的实例化和代码块初始化过程
  7. 10--动作系统(四)动作类中的reverse方法
  8. 为了找到自己的路——leo锦书62
  9. (计蒜客)UCloud 的安全秘钥
  10. java 第三次作业
  11. criteo marketing api 相关
  12. CSS grid 模板
  13. Vue 鼠标移入移出事件
  14. mysql 查询排名 返回值拼接的骚操作
  15. 水题,P1789 【Mc生存】插火把 (暴力即可)
  16. CentOS SSH免密登陆
  17. Git在windows环境下的使用教程
  18. P3704 [SDOI2017]数字表格
  19. caffe Python API 之Accuracy
  20. SpringMVC之HandlerMethodArgumentResolver和&lt;mvc:argument-resolvers&gt;

热门文章

  1. zencart分类页产品页去掉url中的id号
  2. CLR 公共语言运行库
  3. Python开发【第十七篇】:MySQL(一)
  4. jquery左右链接类似frameset的插件
  5. editplus如何配置php编译环境?
  6. 利用afxDump来调试自己的程序
  7. 黑客攻防技术宝典Web实战篇(二)工具篇
  8. [译]我是怎么构建Node.js程序的
  9. Ionic 常见问题及解决方案
  10. Python网络socket学习