PHP多進程編程(三)多進程抓取網頁的示範

來源:互聯網
上載者:User
要理解這個部分的代碼,請閱讀:

PHP多進程編程(一)

PHP多進程編程(二)管道通訊

我們知道,從父進程到子經常的資料傳遞相對比較容易一些,但是從子進程傳遞到父進程就比較的困難。

有很多辦法實現進程互動,在php中比較方便的是 管道通訊。當然,還可以通過 socket_pair 進行通訊。

首先是伺服器為了應對每一個請求要做的事情(發送一個url 序列,url序列用t 分割。而結束標記是 n)

function clientHandle($msgsock, $obj){    $nbuf = '';    socket_set_block($msgsock);    do {        if (false === ($buf = @socket_read($msgsock, 2048, PHP_NORMAL_READ))) {            $obj->error("socket_read() failed: reason: " . socket_strerror(socket_last_error($msgsock)));            break;        }        $nbuf .= $buf;        if (substr($nbuf, -1) != "\n") {            continue;        }        $nbuf = trim($nbuf);        if ($nbuf == 'quit') {            break;        }        if ($nbuf == 'shutdown') {            break;        }        $url = explode("\t", $nbuf);        $nbuf = '';        $talkback = serialize(read_ntitle($url));        socket_write($msgsock, $talkback, strlen($talkback));        debug("write to the client\n");        break;    } while (true);}

上面代碼比較關鍵的一個部分是 read_ntitle,這個函數實現多線程的讀取標題。

代碼如下:(為每一個url fork 一個線程,然後開啟管道 ,讀取到的標題寫入到管道裡面去,主線程一直的在讀取管道資料,直到所有的資料讀取完畢,最後刪除管道)

function read_ntitle($arr){    $pipe = new Pipe("multi-read");    foreach ($arr as $k => $item)    {        $pids[$k] = pcntl_fork();        if(!$pids[$k])        {             $pipe->open_write();             $pid = posix_getpid();             $content = base64_encode(read_title($item));             $pipe->write("$k,$content\n");             $pipe->close_write();             debug("$k: write success!\n");             exit;        }    }    debug("read begin!\n");    $data = $pipe->read_all();    debug("read end!\n");$pipe->rm_pipe();return parse_data($data);}parse_data 代碼如下,非常的簡單,就不說了。parse_data  代碼如下,非常的簡單,就不說了。function parse_data($data){    $data = explode("\n", $data);    $new = array();    foreach ($data as $value)    {        $value = explode(",", $value);        if (count($value) == 2) {            $value[1] = base64_decode($value[1]);            $new[intval($value[0])] = $value[1];        }    }    ksort($new, SORT_NUMERIC);    return $new;}

上面代碼中,還有一個函數read_title 比較有技巧。為了相容性,我沒有採用curl,而是直接採用socket 通訊。

在下載到 title 標籤後,就停止讀取內容,以節省時間。代碼如下:

function read_title($url){    $url_info = parse_url($url);    if (!isset($url_info['host']) || !isset($url_info['scheme'])) {     return false;    }    $host = $url_info['host'];     $port = isset($url_info['port']) ? $url_info['port'] : null; $path = isset($url_info['path']) ? $url_info['path']  : "/"; if(isset($url_info['query'])) $path .= "?".$url_info['query']; if(empty($port)){  $port = 80; } if ($url_info['scheme'] == 'https'){  $port = 443; } if ($url_info['scheme'] == 'http') {  $port = 80; }    $out = "GET $path HTTP/1.1\r\n";    $out .= "Host: $host\r\n";    $out .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.7)\r\n";    $out .= "Connection: Close\r\n\r\n";    $fp = fsockopen($host, $port, $errno, $errstr, 5);    if ($fp == NULL) {     error("get title from $url, error. $errno: $errstr \n");     return false;    }    fwrite($fp, $out);    $content = '';    while (!feof($fp)) {        $content .= fgets($fp, 1024);        if (preg_match("/(.*?)<\/title>/is", $content, $matches)) {             fclose($fp);            return encode_to_utf8($matches[1]);        }    }    fclose($fp);    return false;}function encode_to_utf8($string) {     return mb_convert_encoding($string, "UTF-8", mb_detect_encoding($string, "UTF-8, GB2312, ISO-8859-1", true));}</pre>   

這裡,我只是檢測了 三種最常見的編碼。其他的代碼都很簡單,這些代碼都是測試用的,如果你要做這樣一個伺服器,一定要進行最佳化處理。特別是,要防止一次開啟太多的進程,你要做更多的處理。

很多時候,我們抱怨php 不支援多進程,實際上,php是支援多進程的。當然,沒有那麼多的進程通訊的選項,而多進程的核心就在於進程的通訊與同步。在web開發中,這樣的多線程基本上是不會使用的,因為有很嚴重的效能問題。要實現比較簡單的多進程,高負載,必須藉助其擴充。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.