1

我们正在用 PHP 编写一个与 SEO 相关的脚本,一旦完成爬取过程,我们需要同时运行不同的模块(每个模块都是一个文件 .php)。换句话说,我们需要并行执行 10 多个 .php 文件。

该应用程序曾经使用序列,因此当一个脚本结束时,用户的浏览器会被转发到下一个脚本。每个脚本都与数据库建立连接,并将不同的 HTTP 数据包发送到爬取的 Web 应用程序。

我知道这可以使用 popen 来解决?有没有办法从每个模块接收信息到触发它们的主脚本中?任何人都可以提供一个非常简短的片段来看看它是如何工作的吗?

4

2 回答 2

1

如果 PHP 中的各种文件没有依赖关系,我认为您可以使用多卷曲方法,该方法可以实现如下所示:-

    $linkArray = array('file1.php', 'file2.php','file3.php','file4.php','file5.php');
    $nodes = ($linkArray);
    $node_count = count($nodes);

    $curl_arr = array();
    $master = curl_multi_init();
    $counter = 0;
    for($i = 0; $i < $node_count; $i++)
    {
      $url =$nodes[$i];
      $curl_arr[$i] = curl_init($url);
      curl_setopt($curl_arr[$i], CURLOPT_RETURNTRANSFER, true);
      curl_multi_add_handle($master, $curl_arr[$i]);
    }

do {
    curl_multi_exec($master,$running);
} while($running > 0);

for($k=0;$k<$node_count;$k++){

  $result = curl_multi_getcontent  ($curl_arr[$k]); // contains the output of individual files

}
于 2012-10-25T13:55:41.827 回答
1

尝试使用这种技术在 PHP 中运行多个并行作业。在此示例中,我们有两个作业文件:我们要运行的 j1.php 和 j2.php。示例作业没有做任何花哨的事情。文件 j1.php 如下所示:

$jobname = 'j1';
set_time_limit(0);
$secs = 60;

while ($secs) {
        echo $jobname,'::',$secs,"\n";
        flush(); @ob_flush();  ## make sure that all output is sent in real-time
        $secs -= 1;
        $t = time();
        sleep(1); // pause
}

我们flush()的原因;@ob_flush(); 是当我们回显或打印时,字符串有时会被 PHP 缓冲,直到稍后才发送。这两个功能确保立即发送所有数据。

然后我们有第三个文件 control.php,它负责协调作业 j1 和 j2。该脚本将使用 JobStartAsync() 中的 fsockopen 异步调用 j1.php 和 j2.php,因此我们能够并行运行 j1.php 和 j2.php。使用 JobPollAsync() 将 j1.php 和 j2.php 的输出返回到 control.php。

#
# control.php
#
function JobStartAsync($server, $url, $port=80,$conn_timeout=30, $rw_timeout=86400)
{
    $errno = '';
    $errstr = '';

    set_time_limit(0);

    $fp = fsockopen($server, $port, $errno, $errstr, $conn_timeout);
    if (!$fp) {
       echo "$errstr ($errno)<br />\n";
       return false;
    }
    $out = "GET $url HTTP/1.1\r\n";
    $out .= "Host: $server\r\n";
    $out .= "Connection: Close\r\n\r\n";

    stream_set_blocking($fp, false);
    stream_set_timeout($fp, $rw_timeout);
    fwrite($fp, $out);

    return $fp;
}

// returns false if HTTP disconnect (EOF), or a string (could be empty string) if still connected
function JobPollAsync(&$fp) 
{
    if ($fp === false) return false;

    if (feof($fp)) {
        fclose($fp);
        $fp = false;
        return false;
    }

    return fread($fp, 10000);
}

###########################################################################################


if (1) {  /* SAMPLE USAGE BELOW */

    $fp1 = JobStartAsync('localhost','/jobs/j1.php');
    $fp2 = JobStartAsync('localhost','/jobs/j2.php');


    while (true) {
        sleep(1);

        $r1 = JobPollAsync($fp1);
        $r2 = JobPollAsync($fp2);

        if ($r1 === false && $r2 === false) break;

        echo "<b>r1 = </b>$r1<br>";
        echo "<b>r2 = </b>$r2<hr>";
        flush(); @ob_flush();
    }

    echo "<h3>Jobs Complete</h3>";
}

好读

PHP中的分而治之和并行处理

从源头

于 2012-10-25T13:45:46.423 回答