PHPackages                             fi1a/crawler - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. fi1a/crawler

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

fi1a/crawler
============

PHP crawler

10PHP

Since Feb 22Pushed 3y ago1 watchersCompare

[ Source](https://github.com/fi1a/crawler)[ Packagist](https://packagist.org/packages/fi1a/crawler)[ RSS](/packages/fi1a-crawler/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

PHP crawler (парсинг сайта)
===========================

[](#php-crawler-парсинг-сайта)

[![Latest Version](https://camo.githubusercontent.com/ad11fb44883f883a6770f94aadf459ca69658fae434f52e00c7704114526e745/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f666931612f637261776c65723f6c6162656c3d72656c65617365)](https://packagist.org/packages/fi1a/crawler)[![Software License](https://camo.githubusercontent.com/f1a43d7677becd7eaca319558f13036fe1374866a7b8b82d4ca1c28a3d985119/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f666931612f637261776c65723f7374796c653d666c61742d737175617265)](https://github.com/fi1a/crawler/blob/master/LICENSE)[![PHP Version](https://camo.githubusercontent.com/1c39c707a7a1c7c8f0bc27e394a5d0bc9b49e9c137ca525c4c5f325b171bc199/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f666931612f637261776c65723f7374796c653d666c61742d737175617265)](https://php.net)[![Coverage Status](https://camo.githubusercontent.com/0c967d746eb7f4fe28065a3b94d23faa207cd6f4a968535b20fce0310a87cf89/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f7665726167652d3130302532352d677265656e)](https://camo.githubusercontent.com/0c967d746eb7f4fe28065a3b94d23faa207cd6f4a968535b20fce0310a87cf89/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f7665726167652d3130302532352d677265656e)[![Total Downloads](https://camo.githubusercontent.com/74b16fc40c94e1f53795e815a63e9f8b80a3ecc039190d2babdeeb3e73d9be73/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f666931612f637261776c65722e7376673f7374796c653d666c61742d73717561726526636f6c6f72423d6d656469756d76696f6c6574726564)](https://packagist.org/packages/fi1a/crawler)[![Support mail](https://camo.githubusercontent.com/116fa0d447870a3a6c6c1f4b296c889707a6e30a69c2b28cbe8d0f6f5c3d4920/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6d61696c2d737570706f7274253430666931612e72752d627269676874677265656e)](mailto:support@fi1a.ru)

Этот пакет предоставляет API для обхода ссылок и скачивания файлов (парсинга сайта). С помощью данного пакета вы можете забирать любую информацию со стороннего сайта. Есть возможность создать собственные обработчики, которые позволят кастомизировать логику парсинга страницы, подготовки и сохранения.

Установка
---------

[](#установка)

Установить этот пакет можно как зависимость, используя Composer.

```
composer require fi1a/crawler
```

Шаги процесса парсинга
----------------------

[](#шаги-процесса-парсинга)

Процесс парсинга разделен на три шага:

1. загрузка;
2. процесс;
3. запись.

На шаге "загрузка" осуществляется обход страниц или файлов и их загрузка. Парсинг новых ссылок из загруженной страницы осуществляется классом реализующим интерфейс `Fi1a\Crawler\UriParsers\UriParserInterface`. Определение загружать адрес или нет осуществляется классом реализующим интерфейс `Fi1a\Crawler\Restrictions\RestrictionInterface`.

Шаг "процесс" идет следующим за шагом "загрузка". На данном шаге осуществляется преобразование адресов классом реализующим интерфейс `Fi1a\Crawler\UriTransformers\UriTransformerInterface`.

Последним шагом идет шаг "запись". Перед записью осуществляется подготовка контента с помощью класса реализующего интерфейс `Fi1a\Crawler\PrepareItems\PrepareItemInterface` (класс `Fi1a\Crawler\PrepareItems\PrepareHtmlItem`заменяет старые ссылки на новые). Запись осуществляется с помощью `Fi1a\Crawler\Writers\WriterInterface`.

Методом `run` класса `Fi1a\Crawler\Crawler` запускается все три шага последовательно, но можно запускать шаги поочередно методами `download` (шаг загрузки), `process` (шаг процесса) и `write` (шаг записи).

Примеры
-------

[](#примеры)

Ниже представлены наиболее часто встречающиеся задачи для обхода веб-сайтов.

### Создание копии сайта

[](#создание-копии-сайта)

С помощью представленного кода можно создать копию веб-сайта `https://some-domain.ru`в указанной директории `__DIR__ . '/local-site'`.

```
use Fi1a\Crawler\Config;
use Fi1a\Crawler\ConfigInterface;
use Fi1a\Crawler\Crawler;
use Fi1a\Crawler\ItemStorages\ItemStorage;
use Fi1a\Crawler\ItemStorages\StorageAdapters\LocalFilesystemAdapter;
use Fi1a\Crawler\Writers\FileWriter;

$config = new Config();

$config->setVerbose(ConfigInterface::VERBOSE_DEBUG)
    ->setSizeLimit('5Mb')
    ->addStartUri('https://some-domain.ru');

$crawler = new Crawler($config, new ItemStorage(new LocalFilesystemAdapter(__DIR__ . '/runtime/storage')));

$crawler->setWriter(new FileWriter(__DIR__ . '/local-site'));

$crawler->run();
```

Для начала нужно создать объект конфигурации `Config` и передать его в конструктор класса `Crawler` вместе с объектом класса `ItemStorage`. Затем установить объект `FileWriter` с помощью метода `setWriter` класса `Crawler`реализующего логику сохранения элементов (страниц, файлов) в локальную файловую систему.

Запуск парсинга сайта осуществляется с помощью метода `run` класса `Crawler`.

### Парсинг новостей

[](#парсинг-новостей)

Класс парсера ссылок новостей. Находит на странице списка и возвращает ссылки относящиеся к детальной новости и к списку.

```
namespace Foo\UriParsers;

use Fi1a\Console\IO\ConsoleOutputInterface;
use Fi1a\Crawler\ItemInterface;
use Fi1a\Crawler\UriCollection;
use Fi1a\Crawler\UriCollectionInterface;
use Fi1a\Crawler\UriParsers\UriParserInterface;
use Fi1a\Http\Uri;
use Fi1a\Log\LoggerInterface;
use Fi1a\SimpleQuery\SimpleQuery;
use InvalidArgumentException;

/**
 * Парсер ссылок новостей
 */
class NewsUriParser implements UriParserInterface
{
    /**
     * @inheritDoc
     */
    public function parse(
        ItemInterface $item,
        ConsoleOutputInterface $output,
        LoggerInterface $logger
    ): UriCollectionInterface {
        $collection = new UriCollection();

        if (
            !$item->isAllow()
            || $item->getItemUri()->host() !== 'news-domain.ru'
            || $item->getItemUri()->path() !== '/news/'
        ) {
            return $collection;
        }

        $sq = new SimpleQuery((string) $item->getBody());

        // выбираем ссылки ведущие на детальную новости и ссылки постраничной навигации
        $nodes = $sq('#news .header, #news .pm_s, #news .pm_n');
        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            $value = $sq($node)->attr('href');
            if (!is_string($value) || !$value) {
                continue;
            }
            try {
                $uri = new Uri($value);
            } catch (InvalidArgumentException $exception) {
                continue;
            }

            $collection[] = $uri;
        }

        return $collection;
    }
}
```

Класс преобразования ссылок. Преобразует ссылки новостей из формата источника в новый формат ( =&gt; /news/news-code-1/).

```
namespace Foo\UriTransformers;

use Fi1a\Console\IO\ConsoleOutputInterface;
use Fi1a\Crawler\ItemInterface;
use Fi1a\Crawler\UriTransformers\UriTransformerInterface;
use Fi1a\Http\UriInterface;
use Fi1a\Log\LoggerInterface;

/**
 * Преобразует uri новостей из внешних адресов в новые
 */
class NewsUriTransformer implements UriTransformerInterface
{
    /**
     * @inheritDoc
     */
    public function transform(
        ItemInterface $item,
        ConsoleOutputInterface $output,
        LoggerInterface $logger
    ): UriInterface {
        if (!$item->isAllow()) {
            return $item->getItemUri();
        }

        $isNewsPage = preg_match(
            '#https://news-domain.ru/news/(.+)\.html#mui',
            $item->getItemUri()->uri(),
                $matches
        ) > 0;

        if (!$isNewsPage) {
            $output->writeln('    - Не является ссылкой на новость');

            return $item->getItemUri();
        }

        // Преобразуем ссылки на новости в новый формат
        $object = $item->getItemUri()
            ->withHost('')
            ->withPort(null)
            ->withPath('/news/' . $matches[1] . '/');

        return $object;
    }
}
```

Класс подготавливает HTML новости удаляя "хлебные крошки" и блоки не относящиеся к контенту новости.

```
namespace Foo\PrepareItems;

use Fi1a\Console\IO\ConsoleOutputInterface;
use Fi1a\Crawler\ItemCollectionInterface;
use Fi1a\Crawler\ItemInterface;
use Fi1a\Crawler\PrepareItems\PrepareHtmlItem;
use Fi1a\Log\LoggerInterface;
use Fi1a\SimpleQuery\SimpleQuery;

/**
 * Подготавливает HTML новости
 */
class NewsPrepareItem extends PrepareHtmlItem
{
    /**
     * @inheritDoc
     */
    public function prepare(
        ItemInterface $item,
        ItemCollectionInterface $items,
        ConsoleOutputInterface $output,
        LoggerInterface $logger
    ) {
        $isNewsPage = preg_match(
            '#https://news-domain.ru/news/(.+)\.html#mui',
            $item->getItemUri()->uri()
        ) > 0;

        if (!$isNewsPage) {
            return false;
        }

        $sq = new SimpleQuery((string) $item->getBody(), 'UTF-8');

        $news = $sq('#news');
        // Удаляем лишние элементы, остается только новость с заголовком и контентом
        $news('.share, .breadcrumbs, p:last-child')->remove();

        // Заменяем ссылки на новые ссылки новостей
        $this->replace('a', 'href', $news, $item, $items);

        return $news->html();
    }
}
```

Класс добавляющий/обновляющий новости на сайте 1С-Битрикс записывая их в ИБ.

```
namespace Foo\Writers;

use ErrorException;
use Fi1a\Console\IO\ConsoleOutputInterface;
use Fi1a\Crawler\ItemInterface;
use Fi1a\Crawler\Writers\WriterInterface;
use Fi1a\Log\LoggerInterface;
use Fi1a\SimpleQuery\SimpleQuery;
use Bitrix\Main\Loader;
use Bitrix\Iblock\IblockTable;

/**
 * Записывает результат в ИБ 1С-Битрикса
 */
class NewsWriter implements WriterInterface
{
    /**
     * @var int
     */
    protected $newsIblockId;

    public function __construct()
    {
        Loader::includeModule('iblock');

        $iblock = IblockTable::query()
            ->setSelect(['ID',])
            ->where('CODE', '=', 'furniture_news_s1')
            ->exec()
            ->fetch();

        if (!$iblock) {
            throw new ErrorException('Инфоблок новостей не найден');
        }

        $this->newsIblockId = (int) $iblock['ID'];
    }

    /**
     * @inheritDoc
     */
    public function write(ItemInterface $item, ConsoleOutputInterface $output, LoggerInterface $logger): bool
    {
        $isNewsPage = preg_match(
                '#https://news-domain.ru/news/(.+)\.html#mui',
                $item->getItemUri()->uri(),
                $matches
            ) > 0;

        if (!$isNewsPage) {
            $output->writeln('    - Не является страницей новости');

            return false;
        }

        $sq = new SimpleQuery((string) $item->getPrepareBody(), 'UTF-8');

        $name = $sq('h1')->html();
        $sq('h1')->remove();
        $code = $matches[1];
        $detailText = $sq('body')->html();
        $previewText = \TruncateText(strip_tags($detailText), 50);

        $fields = [
            'IBLOCK_ID' => $this->newsIblockId,
            'NAME' => $name,
            'CODE' => $code,
            'DETAIL_TEXT' => $detailText,
            'DETAIL_TEXT_TYPE' => 'html',
            'PREVIEW_TEXT' => $previewText,
            'ACTIVE' => 'Y',
        ];

        $news = \CIBlockElement::GetList([], [
            '=IBLOCK_ID' => $this->newsIblockId,
            '=CODE' => $code,
        ], false, false, ['ID'])->Fetch();

        $instance = new \CIBlockElement();

        if ($news) {
            $result = $instance->Update($news['ID'], $fields);
            if ($result === false) {
                $output->writeln('    Не удалось обновить новость: {{}}', [$instance->LAST_ERROR]);
            }

            return $result;
        }

        $newsId = (int) $instance->Add($fields);

        if (!$newsId) {
            $output->writeln('    Не удалось создать новость: {{}}', [$instance->LAST_ERROR]);

            return false;
        }

        return true;
    }
}
```

Создается объект конфигурации `Config` со значениями:

- уровень подробности вывода;
- время жизни элементов в хранилище (0 - без ограничения);
- ограничение на загружаемый файл (5Mb для всех типов файлов);
- добавляется точка входа, с которой начинается обход ( - список новостей)

Устанавливаем классы определяющие поведение:

- метод `setUriParser` устанавливает парсер uri для обхода (в зависимости от типа контента);
- метод `setUriTransformer` устанавливает класс преобразователь адресов из внешних во внутренние;
- метод `setPrepareItem` устанавливает класс подготавливающий контент (удаляет лишние теги не относящиеся к новости);
- метод `setWriter` устанавливает класс записывающий результат обхода (записывает новость в ИБ 1С-Битрикса).

Методом `loadFromStorage` класса `Fi1a\Crawler\Crawler` загружаем из хранилища обработанные элементы с последнего запуска и для страниц списка новостей, отмечаем повторную обработку с целью найти новые добавленные новости.

Запускаем парсинг новостей методом `run` класса `Fi1a\Crawler\Crawler`.

```
use Fi1a\Crawler\Config;
use Fi1a\Crawler\ConfigInterface;
use Fi1a\Crawler\Crawler;
use Fi1a\Crawler\ItemInterface;
use Fi1a\Crawler\ItemStorages\ItemStorage;
use Fi1a\Crawler\ItemStorages\StorageAdapters\LocalFilesystemAdapter;
use Fi1a\Http\Mime;
use Foo\PrepareItems\NewsPrepareItem;
use Foo\UriParsers\NewsUriParser;
use Foo\UriTransformers\NewsUriTransformer;
use Foo\Writers\NewsWriter;

$config = new Config();

$config->setVerbose(ConfigInterface::VERBOSE_DEBUG)
    ->setLifetime(0)
    ->setSizeLimit('5Mb')
    ->addStartUri('https://news-domain.ru/news/');

$crawler = new Crawler($config, new ItemStorage(new LocalFilesystemAdapter(__DIR__ . '/runtime/storage')));

$crawler->setUriParser(new NewsUriParser(), Mime::HTML)
    ->setUriTransformer(new NewsUriTransformer())
    ->setPrepareItem(new NewsPrepareItem())
    ->setWriter(new NewsWriter(), Mime::HTML);

$crawler->loadFromStorage();

// При повторном запуске страницы списка помечаем на повторную обработку для добавления новых новостей
foreach ($crawler->getItems() as $item) {
    assert($item instanceof ItemInterface);
    if (
        !$item->isAllow()
        || $item->getItemUri()->host() !== 'news-domain.ru'
        || $item->getItemUri()->path() !== '/news/'
    ) {
        continue;
    }

    $item->setDownloadStatus(null);
    $item->setProcessStatus(null);
    $item->setWriteStatus(null);
}

$crawler->run();
```

Основные классы пакета:
-----------------------

[](#основные-классы-пакета)

Ниже представлены основные классы пакета. С помощью одних можно настроить поведение парсера, а с помощью других расширить его.

- `Fi1a\Crawler\Crawler` - основной класс пакета;
- `Fi1a\Crawler\Config` - конфигурация парсинга;
- `Fi1a\Crawler\UriCollection` - коллекция адресов.
- `Fi1a\Crawler\Item` - элемент обхода;
- `Fi1a\Crawler\ItemCollection` - коллекция элементов обхода.
- `Fi1a\Crawler\ItemStorages\ItemStorage` - реализует хранилище элементов парсинга;
    - `Fi1a\Crawler\ItemStorages\StorageAdapters\LocalFilesystemAdapter` - адаптер для хранения в локальной файловой системе;
    - `Fi1a\Crawler\ItemStorages\StorageAdapters\FilesystemAdapter` - адаптер для хранения в файловой системе;
- Прокси
    - `Fi1a\Crawler\Proxy\Proxy` - прокси для запроса;
    - `Fi1a\Crawler\Proxy\ProxyCollection` - коллекция прокси;
    - `Fi1a\Crawler\Proxy\ProxyStorage` - реализует хранилище для прокси;
        - `Fi1a\Crawler\Proxy\StorageAdapters\LocalFilesystemAdapter` - адаптер для хранения в локальной файловой системе;
        - `Fi1a\Crawler\Proxy\StorageAdapters\FilesystemAdapter` - адаптер для хранения в файловой системе;
    - Подбор подходящих прокси для запроса
        - `Fi1a\Crawler\Proxy\Selections\FilterByAttempts` - фильтрация прокси по числу ошибок соединения;
        - `Fi1a\Crawler\Proxy\Selections\Limit` - ограничение на кол-во подобранных прокси;
        - `Fi1a\Crawler\Proxy\Selections\OnlyActive` - фильтрация прокси по активности;
        - `Fi1a\Crawler\Proxy\Selections\SortedByTime` - отсортированные по времени использования;
- Классы расширяющие операции
    - Ограничение обхода uri
        - `Fi1a\Crawler\Restrictions\NotAllowRestriction` - запрет на обход для всех uri;
        - `Fi1a\Crawler\Restrictions\UriRestriction` - ограничение по домену и пути;
    - Шаг загрузки
        - `Fi1a\Crawler\UriParsers\HtmlUriParser` - парсит html и возвращает uri для обхода;
    - Шаг преобразования uri
        - `Fi1a\Crawler\UriTransformers\SiteUriTransformer` - преобразует uri из внешних адресов в локальные;
    - Шаг записи
        - `Fi1a\Crawler\PrepareItem\PrepareHtmlItem` - подготавливает HTML элемент (заменяет ссылки страницы на новые);
        - `Fi1a\Crawler\Writers\FileWriter` - записывает результат обхода в файл;

Объект настроек
---------------

[](#объект-настроек)

- `startUri` - точка входа, с которой начинается обход;
    - `addStartUri(string $startUri)` - добавить точку входа;
    - `getStartUri(): array` - возвращает добавленные точки входа;
- `httpClientConfig` - объект настроек http-клиента ([подробнее об объекте настроек](https://github.com/fi1a/http-client#%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BA));
    - `setHttpClientConfig(Fi1a\HttpClient\ConfigInterface $config)` - установить объект настроек http-клиента;
    - `getHttpClientConfig(): Fi1a\HttpClient\ConfigInterface` - возвращает объект настроек http-клиента;
- `httpClientHandler` ("Fi1a\\HttpClient\\Handlers\\StreamHandler") - обработчик запросов (возможные значения: "Fi1a\\HttpClient\\Handlers\\StreamHandler", "Fi1a\\HttpClient\\Handlers\\CurlHandler")
    - `setHttpClientHandler(string $handler)` - установить обработчик запросов;
    - `getHttpClientHandler(): string` - вернуть обработчик запросов;
- `verbose` (ConfigInterface::VERBOSE\_NORMAL) - уровень подробности вывода (возможные значения: ConfigInterface::VERBOSE\_NONE, ConfigInterface::VERBOSE\_NORMAL, ConfigInterface::VERBOSE\_HIGHT, ConfigInterface::VERBOSE\_HIGHTEST, ConfigInterface::VERBOSE\_DEBUG);
    - `setVerbose(int $verbose)` - установить уровень подробности вывода;
    - `getVerbose(): int` - вернуть уровень подробности вывода;
- `logChannel` ("crawler") - канал логирования;
    - `setLogChannel(string $logChannel)` - установить канал логирования;
    - `getLogChannel(): string` - вернуть канал логирования;
- `saveAfterQuantity` (10) - параметр, определяющий через какое новое кол-во элементов сохранять элементы в хранилище;
    - `setSaveAfterQuantity(int $quantity)` - установить параметр, определяющий через какое новое кол-во элементов сохранять элементы в хранилище;
    - `getSaveAfterQuantity(): int` - возвращает параметр, определяющий через какое новое кол-во элементов сохранять элементы в хранилище;
- `lifeTime` (24 \* 60 \* 60) - время жизни элементов в хранилище;
    - `setLifetime(int $lifeTime)` - установить время жизни элементов в хранилище;
    - `getLifetime(): int` - вернуть время жизни элементов в хранилище;
- `delay` (\[0, 0\]) - пауза между запросами;
    - `setDelay($delay)` - установить паузу между запросами (возможные значения: int|array&lt;array-key, int&gt;);
    - `getDelay(): array` - вернуть паузу между запросами;
- `sizeLimits` - ограничение на загружаемый файл по типу контента;
    - `setSizeLimit($sizeLimit, ?string $mime = null)` - установить ограничение на загружаемый файл по типу контента;
    - `getSizeLimits(): array` - возвращает ограничения на загружаемые файлы по типу контента;
- `retry` (3) - кол-во попыток запросов к адресу при http ошибки;
    - `setRetry(int $retry)` - установить кол-во попыток запросов к адресу при http ошибки;
    - `getRetry(): int` - вернуть кол-во попыток запросов к адресу при http ошибки.

Пример:

- установить уровень подробности вывода на самый наивысший уровень ConfigInterface::VERBOSE\_DEBUG;
- ограничение на все загружаемые файлы в 5Mb и на файл типа jpeg в 1Mb;
- пауза между запросами случайным образом от 3 до 10 секунд;
- добавить точку входа `https://some-domain.ru`.

```
use Fi1a\Crawler\Config;
use Fi1a\Crawler\ConfigInterface;

$config = new Config();

$config->setVerbose(ConfigInterface::VERBOSE_DEBUG)
    ->setSizeLimit('5Mb')
    ->setSizeLimit('1Mb', 'image/jpeg')
    ->setDelay([3, 10])
    ->addStartUri('https://some-domain.ru');
```

Ограничение обхода
------------------

[](#ограничение-обхода)

Для ограничения обхода парсером используется класс реализующий интерфейс `Fi1a\Crawler\Restrictions\RestrictionInterface`, добавленный методом `addRestriction` класса `Fi1a\Crawler\Crawler`.

В пакете имеются два класса для реализации ограничения:

- `Fi1a\Crawler\Restrictions\NotAllowRestriction` - запрет на обход;
- `Fi1a\Crawler\Restrictions\UriRestriction` - ограничение по домену и пути;

Пример ограничения обхода папкой news домена some-domain.ru:

```
use Fi1a\Crawler\Restrictions\UriRestriction;

$crawler->addRestriction(new UriRestriction('https://some-domain.ru/news/'));
```

Если не были заданы ограничения при начале шага загрузки, они `Fi1a\Crawler\Restrictions\UriRestriction`добавляются автоматически на основе точек входа заданных методом `addStartUri` объекта конфигурации.

Элемент обхода
--------------

[](#элемент-обхода)

При парсинге объект класса `Fi1a\Crawler\Item` используется как конечная точка адреса содержащая в себе всю необходимую информацию для парсинга.

Методы класса:

МетодОписаниеgetItemUri(): UriInterfaceВозвращает urisetStatusCode(?int $statusCode)Устанавливает код статуса ответаgetStatusCode(): ?intВозвращает код статуса ответаsetReasonPhrase(?string $reasonPhrase)Устанавливает текст причины ассоциированный с кодом статусаgetReasonPhrase(): ?stringВозвращает текст причины ассоциированный с кодом статусаsetDownloadStatus(?bool $status)Запрос выполнен успешно или нетgetDownloadStatus(): ?boolЗапрос выполнен успешно или нетsetProcessStatus(?bool $status)Обработка выполнена успешно или нетgetProcessStatus(): ?boolОбработка выполнена успешно или нетsetWriteStatus(?bool $status)Запись выполнена успешно или нетgetWriteStatus(): ?boolЗапись выполнена успешно или нетsetAllow(bool $allow)Разрешено к обработке или нетisAllow(): boolРазрешено к обработке или нетsetBody(string $body)Установить тело ответаgetBody(): ?stringВернуть тело ответаsetPrepareBody($body)Установить подготовленное тело ответаgetPrepareBody()Вернуть подготовленное тело ответаfree()Очищает тело запросаreset()Сбрасывает состояниеsetContentType(?string $contentType)Установить тип контентаgetContentType(): ?stringВернуть тип контентаsetNewItemUri(UriInterface $newItemUri)Установить новый urigetNewItemUri(): ?UriInterfaceВернуть новый uriexpiresAt(?DateTime $dateTime)Истечет в переданное времяexpiresAfter(?int $lifetime)Истекает через переданное времяgetExpire(): ?DateTimeВозвращает когда закончится срок жизниisExpired(): boolСрок жизни истекgetAbsoluteUri(UriInterface $uri): UriInterfaceВозвращает абсолютный путь относительно элементаisImage(): boolЯвляется ли изображениемisFile(): boolЯвляется ли "файлом"isPage(): boolЯвляется ли "страницей"isCss(): boolЯвляется ли Css файломisJs(): boolЯвляется ли Js файломtoArray(): arrayВ массивstatic fromArray(array $fields)Из массиваПолучить коллекцию элементов обхода можно методом `getItems` класса `Fi1a\Crawler\Crawler`.

Геттеры коллекций элементов обхода
----------------------------------

[](#геттеры-коллекций-элементов-обхода)

После выполнения парсинга или загрузки элементов из хранилища с помощью метода `loadFromStorage`класса `Fi1a\Crawler\Crawler` становится доступна коллекция элементов `Fi1a\Crawler\ItemCollectionInterface`, которую можно получить методом `getItems` класса `Fi1a\Crawler\Crawler`.

У данной коллекции есть вспомогательные методы, позволяющие отфильтровать элементы коллекции по какому либо признаку:

- `getDownloaded` - возвращает успешно загруженные элементы;
- `getProcessed` - возвращает успешно обработанные элементы;
- `getWrited` - возвращает успешно записанные элементы;
- `getImages` - возвращает все элементы изображений;
- `getFiles` - возвращает все элементы файлов;
- `getPages` - возвращает все элементы страниц;
- `getCss` - возвращает все элементы css файлов;
- `getJs` - возвращает все элементы js файлов.

Пример выведет все ссылки на загруженные изображения:

```
$crawler->loadFromStorage();
$collection = $crawler->getItems();

foreach ($collection->getDownloaded()->getImages() as $item) {
    echo $item->getItemUri()->uri() . PHP_EOL;
}
```

Использование прокси при запросах
---------------------------------

[](#использование-прокси-при-запросах)

При парсинге сайтов часто требуется использовать прокси. Данный пакет имеет вспомогательные классы для работы с прокси при запросах.

При работе для записи или чтения информации о прокси используется класс `Fi1a\Crawler\Proxy\ProxyStorage`. Данный класс реализует хранилище прокси. Каким образом будет осуществляться хранение определяется адаптером передаваемым первым аргументов в конструктор (адаптер `Fi1a\Crawler\Proxy\StorageAdapters\LocalFilesystemAdapter` осуществляет хранение прокси в json-файле).

Доступны два типа прокси: http и socks5 прокси. Следующий код добавляет прокси в хранилище:

```
use Fi1a\Crawler\Proxy\Proxy;
use Fi1a\Crawler\Proxy\ProxyStorage;
use Fi1a\Crawler\Proxy\StorageAdapters\LocalFilesystemAdapter;

$proxyStorage = new ProxyStorage(new LocalFilesystemAdapter(__DIR__ . '/runtime'));

$httpProxy = Proxy::factory([
    'type' => 'http',
    'host' => '127.0.0.1',
    'port' => 50100,
    'userName' => 'username',
    'password' => 'password',
]);
$proxyStorage->save($httpProxy);

$httpProxy = Proxy::factory([
    'type' => 'socks5',
    'host' => '127.0.0.1',
    'port' => 50101,
    'userName' => 'username',
    'password' => 'password',
]);
$proxyStorage->save($httpProxy);
```

При следующем запуске парсера данные прокси будут загружены из хранилища и использованы для запросов.

Подбор подходящих прокси осуществляется с помощью классов `Fi1a\Crawler\Proxy\Selections\ProxySelectionInterface`:

- `Fi1a\Crawler\Proxy\Selections\FilterByAttempts` - фильтрация прокси по числу ошибок соединения;
- `Fi1a\Crawler\Proxy\Selections\Limit` - ограничение на кол-во подобранных прокси;
- `Fi1a\Crawler\Proxy\Selections\OnlyActive` - фильтрация прокси по активности;
- `Fi1a\Crawler\Proxy\Selections\SortedByTime` - отсортированные по времени использования;

Следующий код выберет только активные прокси (`OnlyActive`), отфильтрует по числу ошибок (`FilterByAttempts`), отсортирует по времени использования (`SortedByTime`) и вернет одну прокси (`Limit`) для использования в запросе:

```
$crawler->setProxySelection(new Limit(new SortedByTime(new FilterByAttempts(new OnlyActive(), 3)), 1));
```

Пример парсинга сайта с использованием сохраненных прокси в хранилище:

```
use Fi1a\Crawler\Config;
use Fi1a\Crawler\ConfigInterface;
use Fi1a\Crawler\Crawler;
use Fi1a\Crawler\ItemStorages\ItemStorage;
use Fi1a\Crawler\ItemStorages\StorageAdapters\LocalFilesystemAdapter;
use Fi1a\Crawler\Proxy\ProxyStorage;
use Fi1a\Crawler\Proxy\Selections\FilterByAttempts;
use Fi1a\Crawler\Proxy\Selections\Limit;
use Fi1a\Crawler\Proxy\Selections\OnlyActive;
use Fi1a\Crawler\Proxy\Selections\SortedByTime;
use Fi1a\Crawler\Proxy\StorageAdapters\LocalFilesystemAdapter as ProxyStorageLocalFilesystemAdapter;
use Fi1a\Crawler\Writers\FileWriter;

$config = new Config();

$config->setVerbose(ConfigInterface::VERBOSE_DEBUG)
    ->setSizeLimit('5Mb')
    ->addStartUri('https://some-domain.ru');

$crawler = new Crawler(
    $config,
    new ItemStorage(new LocalFilesystemAdapter(__DIR__ . '/runtime/storage')),
    new ProxyStorage(new ProxyStorageLocalFilesystemAdapter(__DIR__ . '/runtime'))
);

$crawler->setProxySelection(new Limit(new SortedByTime(new FilterByAttempts(new OnlyActive(), 3)), 1))
    ->setWriter(new FileWriter(__DIR__ . '/local-site'));

$crawler->run();
```

###  Health Score

13

—

LowBetter than 1% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity2

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity23

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/d4f26c1adaa632741fadf55b1328cbd22ac91282aecfae2027d105df0ddedee4?d=identicon)[fi1a](/maintainers/fi1a)

---

Tags

crawlerphp

### Embed Badge

![Health badge](/badges/fi1a-crawler/health.svg)

```
[![Health](https://phpackages.com/badges/fi1a-crawler/health.svg)](https://phpackages.com/packages/fi1a-crawler)
```

###  Alternatives

[botman/botman

Create messaging bots in PHP with ease.

6.2k1.6M98](/packages/botman-botman)[justinvoelker/yii2-separatedpager

A Yii2 LinkPager that displays the first and last pages inline with other pages.

3076.7k2](/packages/justinvoelker-yii2-separatedpager)[offline/oc-gdpr-plugin

October CMS plugin to make websites GDPR and ePrivacy compliant

383.3k1](/packages/offline-oc-gdpr-plugin)[noki/laravel-xml-converter

Laravel XML Converter is Laravel package for converting XML to JSON and XML to array.

322.0k2](/packages/noki-laravel-xml-converter)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
