设为首页 收藏本站
查看: 926|回复: 0

[经验分享] PHP高级编程之--单线程实现并行抓取网页

[复制链接]
累计签到:2 天
连续签到:1 天
发表于 2015-8-30 11:09:13 | 显示全部楼层 |阅读模式
  钻研PHP很多年,想总结一下自己,但是不知从何说起,那就先谈一些我知道的PHP的用法,这些用法很多有多年的工作经验的人可能都不知道。
  实际中可能用不到,但是用到了,就是体现你实力的时候。
  现在问题是这样的,一个用户,用的是windows 的虚拟服务器,然后呢,当打开一个页面的时候,要并行的抓取大概10个网站的标题显示出来。
  这样的用法很少见,但是,有需求,就得解决。
  
  串行是一个解决方案,但是要等待的时间过长。于是我想到用curl 去并行抓取。不知道的可以参考这篇文章

PHP多线程(四) 内部多线程
  
  但是,最后发现,那个虚拟服务器上没有curl,这真是让人纠结。于是,我决定改变思路,用单个线程也实现多个线程的效果。我想对网络编程有点
  了解的人肯定知道IO复用这个概念,当然PHP上也是支持的,而且,内部支持,不需要任何扩展。
  可能有很多年编程经验的人对PHP的stream 函数可能不太了解。PHP的压缩文件流,文件流,tcp 协议下的应用 都封装成一个stream。所以,读本地文件
  和读网络文件没有任何的差别。说了这样多,我想大家都基本上明白了,直接贴上代码吧:
  代码比较的粗糙,如果大家要实际用的话,还是要处理一些细节问题。
  
  


DSC0000.gif DSC0001.gif 代码



<?php
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)<br />\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.360.cn";
//并行的抓取
$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
  如果,所有网站都差不多的速度,并行的数目更大,那么差的倍数也就越大。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-106259-1-1.html 上篇帖子: 黄聪:最新版wordpress出现:require(wp-blog-header.php) [function.require]: failed to open 下篇帖子: 关于php中用session_destroy不起作用的问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表