• 技术文章 >后端开发 >php教程

    PHP单线程实现并行抓取网页_PHP教程

    2016-07-13 10:22:38原创706

    PHP单线程实现并行抓取网页


      本PHP教程将模拟并行抓取多个页面信息的过程,关键在于单线程的并行处理。

      一般情况下,大家写抓取多个页面信息的程序都采用串行方案,但获取周期过长,不实用。于是我想到用curl 去并行抓取。但是,最后发现,那个虚拟服务器上没有curl,这真是让人纠结。于是,我决定改变思路,用单个线程也实现多个线程的效果。我想对网络编程有点

      了解的人肯定知道IO复用这个概念,当然PHP上也是支持的,而且,内部支持,不需要任何扩展。

      可能有很多年编程经验的人对PHP的stream 函数可能不太了解。PHP的压缩文件流,文件流,tcp 协议下的应用 都封装成一个stream。所以,读本地文件

      和读网络文件没有任何的差别。说了这样多,我想大家都基本上明白了,直接贴上代码吧:

      代码比较的粗糙,如果大家要实际用的话,还是要处理一些细节问题。

      代码

      

      function http_get_open($url)

      {

      $url = parse_url($url);

      if (empty($url['host'])) {

      return false;

      }

      $host = $url['host'];

      if (empty($url['path'])) {

      $url['path'] = "//m.sbmmt.com/m/";

      }

      $get = $url['path'] . "?" . @$url['query'];

      $fp = stream_socket_client("tcp://{$host}:80", $errno, $errstr, 30);

      if (!$fp) {

      echo "$errstr ($errno)
    \n";

      return false;

      } else {

      fwrite($fp, "GET {$get} HTTP/1.0\r\nHost: {$host}\r\nAccept: */*\r\n\r\n");

      }

      return $fp;

      }

      function http_multi_get($urls)

      {

      $result = array();

      $fps = array();

      foreach ($urls as $key => $url)

      {

      $fp = http_get_open($url);

      if ($fp === false) {

      $result[$key] = false;

      } else {

      $result[$key] = '';

      $fps[$key] = $fp;

      }

      }

      while (1)

      {

      $reads = $fps;

      if (empty($reads)) {

      break;

      }

      if (($num = stream_select($reads, $w = null, $e = null, 30)) === false ) {

      echo "error";

      return false;

      } else if ($num > 0) {//can read

      foreach ($reads as $value)

      {

      $key = array_search($value, $fps);

      if (!feof($value)) {

      $result[$key] .= fread($value, 128);

      } else {

      unset($fps[$key]);

      }

      }

      } else {//time out

      echo "timeout";

      return false;

      }

      }

      foreach ($result as $key => &$value)

      {

      if ($value) {

      $value = explode("\r\n\r\n", $value, 2);

      }

      }

      return $result;

      }

      $urls = array();

      $urls[] = "http://www.qq.com";

      $urls[] = "http://www.sina.com.cn";

      $urls[] = "http://www.sohu.com";

      $urls[] = "http://www.blue1000.com";

      //并行的抓取

      $t1 = microtime(true);

      $result = http_multi_get($urls);

      $t1 = microtime(true) - $t1;

      var_dump("cost: " . $t1);

      //串行的抓取

      $t1 = microtime(true);

      foreach ($urls as $value)

      {

      file_get_contents($value);

      }

      $t1 = microtime(true) - $t1;

      var_dump("cost: " . $t1);

      ?>

      最后运行的结果:

      string 'cost: 3.2403128147125' (length=21)

      string 'cost: 6.2333900928497' (length=21)

      基本上是两倍的效率,当然,发现新浪非常的慢,要2.5s 左右,

      基本上是被他给拖累了,360只要 0.2s

      如果,所有网站都差不多的速度,并行的数目更大,那么差的倍数也就越大。

    www.bkjia.comtruehttp://www.bkjia.com/PHPjc/847205.htmlTechArticlePHP单线程实现并行抓取网页 本PHP教程将模拟并行抓取多个页面信息的过程,关键在于单线程的并行处理。 一般情况下,大家写抓取多个页...

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:PHP 单线程 线程 实现 并行 抓取 网页 PHP 单线程 线程 实现 并行 抓取 网页 教程 模拟
    上一篇:PHP上传文件时无法上传成功,$_FILES['screenshot']['tmp_name']为空_PHP教程 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 浅析PHP应用程序中正确调用系统命令的方法• 求解:phpcms模板怎样转码?该怎么解决• 想请问一下印证的有关问题• php 之 cookie 跟 session 简单解读(笔记) • xml转换成数组的有关问题
    1/1

    PHP中文网