分享一个强大的采集类,还可以模拟php多进程

做采集的时候,可以使用file_get_contents()去获取网页源代码,但是使用file_get_contents采集,速度慢,而且超时时间,不好控制。如果采集的页面不存在,需要等待的时间很长。一般来说,curl的速度最快,其次是socket,最后是file_get_contents。
现在跟大家分享一个很强大的采集类,会根据你的服务器当前的配置,自动选择最快的方式。已经封装了curl和socket,file_get_contents

用法很简单:
1,采用get方法请求
Http::doGet(网址);//超市时间可忽略,默认是5秒
Http::doGet(网址,超时时间);
如echo Http::doGet('http://www.baidu.com');

2,采用post方法请求
Http::doPost(网址,数据,超时时间);


$url='http://www.canphp.com/test.php';
$data['name']='单骑';
$data['email']='admin@canphp.com';
Http::doPost($url,$data,10);

test.php页面接收数据
$_POST['name'];
$_POST['email'];

这个http类不仅可以用来采集,还有一个很强大的作用,模拟php异步多进程。
比如有index.php和a.php,  b.php,  c.php
在index.php中
Http::doGet('http://www.canphp.com/a.php',1);
Http::doGet('http://www.canphp.com/b.php',1);
Http::doGet('http://www.canphp.com/c.php',1);

a.php,  b.php,  c.php程序分别在头部加上ignore_user_abort(true);
那么就可以实现多进程了。

原理:
通过curl或socket发送请求给a.php,  b.php,  c.php,由于超时时间比较短,只是触发了a.php,  b.php,  c.php三个页面,不需要等待数据返回,连接已中断,但是a.php,  b.php,  c.php程序中加上了ignore_user_abort(true);忽略客户端连接,还会继续执行。

具体案例可以观看很邪恶很强大的av程序(http://www.canphp.com/bbs/thread-295-1-1.html)
  1. <?php
  2. //数据采集,doGET,doPOST
  3. class Http
  4. {//类定义开始
  5. //通过get方式获取数据
  6. static public function doGet($url,$timeout=5)
  7. {
  8. $code=self::getSupport();
  9. switch($code)
  10. {
  11. case 1:return self::curl($url,'',$timeout);break;
  12. case 2:return self::socketGet($url,$timeout);break;
  13. case 3:return @file_get_contents($url);break;
  14. default:return false;
  15. }
  16. }
  17. //通过POST方式发送数据
  18. static public function doPost($url,$data,$timeout=5)
  19. {
  20. $code=self::getSupport();
  21. switch($code)
  22. {
  23. case 1:return self::curl($url,$data,$timeout);break;
  24. case 2:return self::socketPost($url,$data,$timeout);break;
  25. default:return false;
  26. }
  27. }
  28. //获取支持读取远程文件的方式
  29. static public function getSupport()
  30. {
  31. if(function_exists('curl_init'))//curl方式
  32. {
  33. return 1;
  34. }
  35. else if(function_exists('fsockopen'))//socket
  36. {
  37. return 2;
  38. }
  39. else if(function_exists('file_get_contents'))//php系统函数file_get_contents
  40. {
  41. return 3;
  42. }
  43. else if(ini_get('allow_url_fopen')&&function_exists('fopen'))//php系统函数fopen
  44. {
  45. return 4;
  46. }
  47. else
  48. {
  49. return 0;
  50. }
  51. }
  52. static public function GetHttpContent($fsock=null) {
  53. $out = null;
  54. while($buff = @fgets($fsock, 2048)){
  55. $out .= $buff;
  56. }
  57. fclose($fsock);
  58. $pos = strpos($out, "\r\n\r\n");
  59. $head = substr($out, 0, $pos); //http head
  60. $status = substr($head, 0, strpos($head, "\r\n")); //http status line
  61. $body = substr($out, $pos + 4, strlen($out) - ($pos + 4));//page body
  62. if(preg_match("/^HTTP\/\d\.\d\s([\d]+)\s.*$/", $status, $matches)){
  63. if(intval($matches[1]) / 100 == 2){
  64. return $body;
  65. }else{
  66. return false;
  67. }
  68. }else{
  69. return false;
  70. }
  71. }
  72. static public function socketGet($url,$timeout=5){
  73. $url2 = parse_url($url);
  74. $url2["path"] = isset($url2["path"])? $url2["path"]: "/" ;
  75. $url2["port"] = isset($url2["port"])? $url2["port"] : 80;
  76. $url2["query"] = isset($url2["query"])? "?".$url2["query"] : "";
  77. $host_ip = @gethostbyname($url2["host"]);
  78. $fsock_timeout = $timeout; //超时时间
  79. if(($fsock = fsockopen($host_ip, $url2['port'], $errno, $errstr, $fsock_timeout)) < 0){
  80. return false;
  81. }
  82. $request = $url2["path"] .$url2["query"];
  83. $in = "GET " . $request . " HTTP/1.1\r\n";
  84. $in .= "Accept: */*\r\n";
  85. // $in .= "User-Agent: Payb-Agent\r\n";
  86. $in .= "Host: " . $url2["host"] . "\r\n";
  87. $in .= "Connection: Close\r\n\r\n";
  88. if(!@fwrite($fsock, $in, strlen($in))){
  89. @fclose($fsock);
  90. return false;
  91. }
  92. return self::GetHttpContent($fsock);
  93. }
  94. static public function socketPost($url,$post_data=array(),$timeout=5){
  95. $url2 = parse_url($url);
  96. $url2["path"] = ($url2["path"] == "" ? "/" : $url2["path"]);
  97. $url2["port"] = ($url2["port"] == "" ? 80 : $url2["port"]);
  98. $host_ip = @gethostbyname($url2["host"]);
  99. $fsock_timeout = $timeout; //超时时间
  100. if(($fsock = fsockopen($host_ip, $url2['port'], $errno, $errstr, $fsock_timeout)) < 0){
  101. return false;
  102. }
  103. $request = $url2["path"].($url2["query"] ? "?" . $url2["query"] : "");
  104. $post_data2 = http_build_query($post_data);
  105. $in = "POST " . $request . " HTTP/1.1\r\n";
  106. $in .= "Accept: */*\r\n";
  107. $in .= "Host: " . $url2["host"] . "\r\n";
  108. // $in .= "User-Agent: Lowell-Agent\r\n";
  109. $in .= "Content-type: application/x-www-form-urlencoded\r\n";
  110. $in .= "Content-Length: " . strlen($post_data2) . "\r\n";
  111. $in .= "Connection: Close\r\n\r\n";
  112. $in .= $post_data2 . "\r\n\r\n";
  113. unset($post_data2);
  114. if(!@fwrite($fsock, $in, strlen($in))){
  115. @fclose($fsock);
  116. return false;
  117. }
  118. return self::GetHttpContent($fsock);
  119. }
  120. static public function curl($url, $data=array(), $timeout=5)
  121. {
  122. $ch = curl_init();
  123. if (is_array($data) && $data)
  124. {
  125. $formdata = http_build_query($data);
  126. curl_setopt($ch, CURLOPT_POST, true);
  127. curl_setopt($ch, CURLOPT_POSTFIELDS, $formdata);
  128. }
  129. curl_setopt($ch, CURLOPT_URL, $url);
  130. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  131. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  132. curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  133. $result = curl_exec($ch);
  134. curl_close($ch);
  135. return $result;
  136. }
  137. }//类定义结束
  138. ?>
复制代码

 

<?php
//数据采集,doGET,doPOST
class Http
{//类定义开始
//通过get方式获取数据
static public function doGet($url,$timeout=5)
{
$code=self::getSupport();
switch($code)
{
case 1:return self::curl($url,'',$timeout);break;
case 2:return self::socketGet($url,$timeout);break;
case 3:return @file_get_contents($url);break;
default:return false;
}
}
//通过POST方式发送数据
static public function doPost($url,$data,$timeout=5)
{
$code=self::getSupport();
switch($code)
{
case 1:return self::curl($url,$data,$timeout);break;
case 2:return self::socketPost($url,$data,$timeout);break;
default:return false;
}
}

//获取支持读取远程文件的方式
static public function getSupport()
{
if(function_exists('curl_init'))//curl方式
{
return 1;
}
else if(function_exists('fsockopen'))//socket
{
return 2;
}
else if(function_exists('file_get_contents'))//php系统函数file_get_contents
{
return 3;
}
else if(ini_get('allow_url_fopen')&&function_exists('fopen'))//php系统函数fopen
{
return 4;
}
else
{
return 0;
}
}
static public function GetHttpContent($fsock=null) {
$out = null;
while($buff = @fgets($fsock, 2048)){
$out .= $buff;
}
fclose($fsock);
$pos = strpos($out, "\r\n\r\n");
$head = substr($out, 0, $pos); //http head
$status = substr($head, 0, strpos($head, "\r\n")); //http status line
$body = substr($out, $pos + 4, strlen($out) - ($pos + 4));//page body
if(preg_match("/^HTTP\/\d\.\d\s([\d]+)\s.*$/", $status, $matches)){
if(intval($matches[1]) / 100 == 2){
return $body;
}else{
return false;
}
}else{
return false;
}
}
static public function socketGet($url,$timeout=5){
$url2 = parse_url($url);
$url2["path"] = isset($url2["path"])? $url2["path"]: "/" ;
$url2["port"] = isset($url2["port"])? $url2["port"] : 80;
$url2["query"] = isset($url2["query"])? "?".$url2["query"] : "";
$host_ip = @gethostbyname($url2["host"]);
$fsock_timeout = $timeout; //超时时间
if(($fsock = fsockopen($host_ip, $url2['port'], $errno, $errstr, $fsock_timeout)) < 0){
return false;
}
$request = $url2["path"] .$url2["query"];
$in = "GET " . $request . " HTTP/1.1\r\n";
$in .= "Accept: */*\r\n";
// $in .= "User-Agent: Payb-Agent\r\n";
$in .= "Host: " . $url2["host"] . "\r\n";
$in .= "Connection: Close\r\n\r\n";
if(!@fwrite($fsock, $in, strlen($in))){
@fclose($fsock);
return false;
}
return self::GetHttpContent($fsock);
}

static public function socketPost($url,$post_data=array(),$timeout=5){
$url2 = parse_url($url);
$url2["path"] = ($url2["path"] == "" ? "/" : $url2["path"]);
$url2["port"] = ($url2["port"] == "" ? 80 : $url2["port"]);
$host_ip = @gethostbyname($url2["host"]);
$fsock_timeout = $timeout; //超时时间
if(($fsock = fsockopen($host_ip, $url2['port'], $errno, $errstr, $fsock_timeout)) < 0){
return false;
}
$request = $url2["path"].($url2["query"] ? "?" . $url2["query"] : "");
$post_data2 = http_build_query($post_data);
$in = "POST " . $request . " HTTP/1.1\r\n";
$in .= "Accept: */*\r\n";
$in .= "Host: " . $url2["host"] . "\r\n";
// $in .= "User-Agent: Lowell-Agent\r\n";
$in .= "Content-type: application/x-www-form-urlencoded\r\n";
$in .= "Content-Length: " . strlen($post_data2) . "\r\n";
$in .= "Connection: Close\r\n\r\n";
$in .= $post_data2 . "\r\n\r\n";
unset($post_data2);
if(!@fwrite($fsock, $in, strlen($in))){
@fclose($fsock);
return false;
}
return self::GetHttpContent($fsock);
}

static public function curl($url, $data=array(), $timeout=5)
{
$ch = curl_init();
if (is_array($data) && $data)
{
$formdata = http_build_query($data);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $formdata);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}

}//类定义结束
?>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SimpleFork simple-fork-php 是基于 PCNTL 扩展的进程管理包,接口类似与 Java 的 Thread 和 Runnable 为什么要写 SimpleFork 多进程程序的编写相比较多线程编写更加复杂,需要考虑进程回收、同步、互斥、通信等问题。对于初学者来说,处理上述问题会比较困难。 尤其是信号处理和进程通信这块,很难做到不出问题。 SimpleFork提供一套类似于JAVA多线程的进程控制接口,提供回收、同步、互斥、通信等方案,开发者可以关注业务问题,不需要过多考虑进程控制。 引入 composer require jenner/simple_fork require path/to/SimpleFork/autoload.php 依赖 必须 ext-pcntl 进程控制 可选 ext-sysvmsg 消息队列 ext-sysvsem 同步互斥锁 ext-sysvshm 共享内存 特性 提供进程池 自动处理僵尸进程回收,支持无阻塞调用 提供共享内存、System V 消息队列、Semaphore锁,方便IPC通信(进程通信) 提供Process和Runnable两种方式实现进程 可以实时获取到进程状态 shutdown所有进程或单独stop一个进程时,可以注册覆盖beforeExit()方法,返回true则退出,false继续运行(在某些场景,进程不能立即退出) 支持子进程运行时reload 注意事项 System V 消息队列由于在程序退出时可能存在尚未处理完的数据,所以不会销毁。如果需要销毁,请调用$queue->remove()方法删除队列 共享内存会在所有进程退出后删除 Semaphore对象会在对象回收时进行销毁 进程池start()后,需要调用wait()进行僵尸进程回收,可以无阻塞调用 获取进程状态(调用isAlive()方法)前,最好调用一个无阻塞的wait(false)进行一次回收,由于进程运行状态的判断不是原子操作,所以isAlive()方法不保证与实际状态完全一致 如果你不清楚在什么情况下需要在程序的最开始加入declare(ticks=1);,那么最好默认第一行都加入这段声明。 如何使用declare(ticks=1); declare(ticks=1); 这段声明用于进程信号处理。如果注册了信号处理器,程序会没执行一行代码后自动检查是否有尚未处理的信号。http://php.net/manual/zh/control-structures.declare.php TODO 提供更多功能的进程池,模仿java 提供第三方进程通信机制(Redis等) 更多的测试及示例程序 示例程序 更多示例程序见exmples目录 simple.php class TestRunnable extends \Jenner\SimpleFork\Runnable{ /**      * 进程执行入口      * @return mixed      */ public function run() { echo "I am a sub process" . PHP_EOL;     } } $process = new \Jenner\SimpleFork\Process(new TestRunnable()); $process->start(); shared_memory.php class Producer extends \Jenner\SimpleFork\Process{ public function run(){ for($i = 0; $icache->set($i, $i); echo "set {$i} : {$i}" . PHH_EOL;         }     } } class Worker extends \Jenner\SimpleFork\Process{ public 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值