PHP中的多线程,多卷曲爬虫

Chr*_*sso 7 php parallel-processing curl fork fsockopen

大家好再次!

我们需要一些帮助来在我们的抓取工具中开发和实现多卷曲功能.我们有一大堆"要扫描的链接",我们循环使用Foreach.

让我们使用一些伪代码来理解逻辑:

    1) While ($links_to_be_scanned > 0).
    2) Foreach ($links_to_be_scanned as $link_to_be_scanned).
    3) Scan_the_link() and run some other functions.
    4) Extract the new links from the xdom.
    5) Push the new links into $links_to_be_scanned.
    5) Push the current link into $links_already_scanned.
    6) Remove the current link from $links_to_be_scanned.
Run Code Online (Sandbox Code Playgroud)

现在,我们需要定义最大数量的并行连接,并能够并行地为每个链接运行此过程.

我知道我们必须创建$ links_being_scanned或某种队列.

我真的不确定如何处理这个问题,说实话,如果有人能提供一些片段或想法来解决它,我将不胜感激.

提前致谢!克里斯;

扩展:

我刚刚意识到,多卷曲本身并不是棘手的部分,而是请求后每个链接完成的操作量.

即使在muticurl之后,我最终也必须找到一种方法来并行运行所有这些操作.下面描述的整个算法必须并行运行.

所以现在重新思考,我们必须做这样的事情:

  While (There's links to be scanned)
  Foreach ($Link_to_scann as $link)
  If (There's less than 10 scanners running)
  Launch_a_new_scanner($link)
  Remove the link from $links_to_be_scanned array
  Push the link into $links_on_queue array
  Endif;
Run Code Online (Sandbox Code Playgroud)

每个扫描仪都做(这应该并行运行):

  Create an object with the given link
  Send a curl request to the given link
  Create a dom and an Xdom with the response body
  Perform other operations over the response body
  Remove the link from the $links_on_queue array
  Push the link into the $links_already_scanned array
Run Code Online (Sandbox Code Playgroud)

我假设我们可以使用扫描程序算法创建一个新的PHP文件,并为每个并行进程使用pcntl_fork()?

因为即使使用多卷曲,我最终还是必须等待其他进程的常规foreach结构上的循环.

我假设我必须使用fsockopen或pcntl_fork来解决这个问题.

建议,评论,部分解决方案,甚至是"好运"都将不胜感激!

非常感谢!

rdl*_*rey 9

免责声明:这个答案链接了我参与的一个开源项目.那里.你被警告过了.

ARTAX HTTP客户端是基于套接字的HTTP库(除其他事项外),在打开的并发套接字连接到单个主机的数量提供定制的控制,同时进行多个异步HTTP请求.

可以轻松实现限制并发连接的数量.考虑:

<?php

use Artax\Client, Artax\Response;

require dirname(__DIR__) . '/autoload.php';

$client = new Client;

// Defaults to max of 8 concurrent connections per host
$client->setOption('maxConnectionsPerHost', 2);

$requests = array(
    'so-home'    => 'http://stackoverflow.com',
    'so-php'     => 'http://stackoverflow.com/questions/tagged/php',
    'so-python'  => 'http://stackoverflow.com/questions/tagged/python',
    'so-http'    => 'http://stackoverflow.com/questions/tagged/http',
    'so-html'    => 'http://stackoverflow.com/questions/tagged/html',
    'so-css'     => 'http://stackoverflow.com/questions/tagged/css',
    'so-js'      => 'http://stackoverflow.com/questions/tagged/javascript'
);

$onResponse = function($requestKey, Response $r) {
    echo $requestKey, ' :: ', $r->getStatus();
};

$onError = function($requestKey, Exception $e) {
    echo $requestKey, ' :: ', $e->getMessage();
}

$client->requestMulti($requests, $onResponse, $onError);
Run Code Online (Sandbox Code Playgroud)

重要信息:在上面的示例中,该Client::requestMulti方法异步发出所有指定的请求.由于每主机并发限制设置为2,客户端将为前两个请求打开新连接,然后为其他请求重用这些相同的套接字,排队请求,直到两个套接字中的一个可用.