cobaia/marsvin

Marsvin 是一个用于编写爬虫应用的框架

v1.0.0 2013-01-21 05:32 UTC

This package is not auto-updated.

Last update: 2024-09-14 12:34:23 UTC


README

#Marsvin

这是什么?

你曾经编写过爬虫或解析器吗?

如果是,你肯定知道这总是一个简单的任务,但我们总是要思考如何构建代码来执行此类操作...

所以...为了解决这个问题,Marvins 被创建出来,Marvins 提供了一个简单的 API 和结构,供您创建自己的解析器或爬虫。主要关注的是简化从外部资源解析数据、从网站提取数据或从 XML、CSV 文件等导入数据的任务...

而且还有更多,作为额外功能,它还包含进程管理,这使得您能够同时打开多个 PHP 进程,因此您能够同时做很多事情。

如何使用它?

创建一个 composer.json

{
  "name" : "your/projectname",
  "require" : {
    "cobaia/marsvin" : "dev-master"
  },
  "minimum-stability" : "dev"
}

运行以下命令

composer.phar install

创建您的控制台命令

文件: console.php

<?php
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;

$console = new Application('Your Project', '1.0');
$console->addCommands(
    array(
            new Marsvin\Command\GenerateProviderCommand(),
            new Marsvin\Command\RequestProviderCommand(),
    )
);

//You are able to pass as much helper set you want, like Doctrine, Monolog, etc...
//$console->setHelperSet($helperSet);
$console->run();

创建控制台后,您已经可以运行以下命令:php app/console.php

您将检查我们有两个命令可以使用

marsvin
  marsvin:generate:provider   Generate Provider code structure
  marsvin:request:provider    Request one specific Provider

Marsvin 使用以下命名约定

  • 提供者:这是您将要执行的操作的名称,例如,Facebook、Github、Google 等。
  • 请求者:这是负责向提供者发起请求的层,例如,对于 Facebook,可能是 HTTP 请求,对于 Github,可能是一次 Git 操作,对于其他提供者,可能是 FTP 访问等。
  • 解析器:一旦请求操作完成,解析器层就会进入,这一层将负责数据,所以如果您想设置 doctrine 的某些实体或创建数据数组等,或者您想以某种方式规范化数据,这就是您将使用的层来完成此类任务。
  • 持久化器:一旦解析了数据,它就会进入持久化器层,在这里您可以对数据进行任何操作,例如,在 doctrine 中,您可以将数据持久化和刷新到数据库,或者如果您想将数据持久化到文件系统、发送电子邮件等,持久化器层将为您处理这些操作。

创建我们的第一个提供者

要创建我们的提供者,Marvins 提供了一个命令来为您创建文件夹结构

php app/console marsvin:generate:provider MyProject\\Github ./src/

您将检查 Marsvin 会为您生成以下文件夹树

.
└── MyProject
    └── Github
        ├── GithubParser.php
        ├── GithubPersister.php
        ├── GithubProvider.php
        └── GithubRequester.php

现在是时候设置适配器了,Marvins 使用适配器模式来定义每一层,例如,如果您想进行 HTTP 请求,您可以在请求者层设置一个 HttpAdapter 来使用。

默认情况下,Marvins 包含一些适配器

  • 请求者:DefaultAdapter.php BuzzAdapter.php
  • 解析器:DomAdapter.php
  • 持久化器:DefaultAdapter.php DoctrineAdapter.php

因此,让我们设置我们的提供者

<?php
namespace MyProject\Github;

use Marsvin\Provider\AbstractProvider;
use Marsvin\Provider\ProviderInterface;
use Marsvin\Requester\Adapter\BuzzAdapter;
use Marsvin\Parser\Adapter\DomAdapter;
use Marsvin\Persister\Adapter\DefaultAdapter;

class GithubProvider extends AbstractProvider implements ProviderInterface
{

    public function getRequesterAdapter()
    {
        return new BuzzAdapter();
    }

    public function getParserAdapter()
    {
        return new DomAdapter();
    }

    public function getPersisterAdapter()
    {
        return new DefaultAdapter();
    }

}

请求者

<?php
namespace MyProject\Github;

use Marsvin\Requester\AbstractRequester;
use Marsvin\Requester\RequesterInterface;
use Marsvin\Response;

class GithubRequester extends AbstractRequester implements RequesterInterface
{

    const GITHUB_URL = 'https://github.com/%s?tab=repositories';

    public function request()
    {
        $adapter = $this->getAdapter();

        $profiles = array(
            'krolow',
            'gquental',
            'moacirosa',
            'fabpot',
        );

        $self = $this;

        foreach ($profiles as $profile) {
            $this->process(function () use ($self, $adapter, $profile) {
                $self->done(
                    new Response(
                        $adapter->request(
                            sprintf(
                                GithubRequester::GITHUB_URL,
                                $profile
                            )
                        )
                    )
                );
            });
        }
    }

}

解析器

<?php
namespace MyProject\Github;

use Marsvin\Parser\AbstractParser;
use Marsvin\Parser\ParserInterface;
use Marsvin\Response;
use Marsvin\ResponseInterface;
use DOMXPath;
use DOMDocument;

class GithubParser extends AbstractParser implements ParserInterface
{

    public function parse(ResponseInterface $response)
    {
        $adapter = $this->getAdapter();

        $dom = $adapter->parse($response->get());

        $xpath = new DOMXPath($dom);
        
        $nodes = $xpath->query('//span[@itemprop="name"]');
        $author = $nodes->item(0)->nodeValue;

        $nodes = $xpath->query('//li[contains(@class, "public")]');

        $projects = array();

        foreach ($nodes as $node) {
            array_push(
                $projects,
                $this->parseProject($node, $author)
            );
        }


        $this->done(new Response($projects));
    }

    protected function parseProject($node, $author)
    {
        $doc = new DOMDocument();
        $doc->appendChild($doc->importNode($node, true));

        $name = $doc->getElementsByTagName('h3');
        $url = $doc->getElementsByTagName('a');

        $project = array(
            'name' => trim($name->item(0)->nodeValue),
            'url' => 'http://github.com/' . $url->item(2)->getAttribute('href'),
            'author' => $author
        );
        
        return $project;
    }

}

持久化器

<?php
namespace MyProject\Github;

use Marsvin\Persister\AbstractPersister;
use Marsvin\Persister\PersisterInterface;
use Marsvin\Response;
use Marsvin\ResponseInterface;

class GithubPersister extends AbstractPersister implements PersisterInterface
{

    public function persists(ResponseInterface $response)
    {
        $adapter = $this->getAdapter();
        $adapter->persist($response->get());
        file_put_contents('/tmp/marsvin.log', var_export($adapter->flush(), true), FILE_APPEND);
    }

}

要运行命令,请执行以下操作

php app/console.php marsvin:request:provider MyProject\\Github\\GithubProvider

您可以通过以下方式检查这里正在发生什么

tail -f /tmp/marsvin.log