您当前的位置: 首页 > 网站编程 > PHP教程 > PHP单线程实现并行抓取网页

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

作者:不详 来源:网络 发布时间: 2014-07-30 10:16 点击:
本PHP教程将模拟并行抓取多个页面信息的过程,关键在于单线程的并行处理。 一般情况下,大家写抓取多个页面信息的程序都采用串行方案,但获取周期过长,不实用。于是我想到用curl 去并行抓龋但是,最后发现,那个虚拟服务器上没有curl,这真是让人纠结。于是,我决定改

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'] = "/";

  }

  $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.0rnHost: {$host}rnAccept: */*rnrn");

  }

  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("rnrn", $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

  如果,所有网站都差不多的速度,并行的数目更大,那么差的倍数也就越大。
分享到:
本文"PHP单线程实现并行抓取网页"由远航站长收集整理而来,仅供大家学习与参考使用。更多网站制作教程尽在远航站长站。
顶一下
(0)
0%
踩一下
(0)
0%
[点击 次] [返回上一页] [打印]
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
关于本站 - 联系我们 - 网站声明 - 友情连接- 网站地图 - 站点地图 - 返回顶部
Copyright © 2007-2013 www.yhzhan.com(远航站长). All Rights Reserved .
远航站长:为中小站长提供最佳的学习与交流平台,提供网页制作与网站编程等各类网站制作教程.
官方QQ:445490277 网站群:26680406 网站备案号:豫ICP备07500620号-4