Парсинг внешнего сайта на Yii 2.x (часть 1)

Иногда необходимо извлечь данные с сайта в автоматическом режиме, не прибегая к ручному копированию. Это может быть новостная лента, гороскоп, погода, программа телепередач и т.д. Рассмотрим пример на Yii2 и прокомментируем его.

Для реализации парсинга нам необходимо установить библиотеки Guzzle и phpQuery

Устанавливаем с помощью composer Guzzle (Guzzle работает с версией PHP 5.5 и выше)

composer require guzzlehttp/guzzle:~6.0

Используем следующую библиотеку для работы с phpQuery и устанавливаем ее так же с помощью Composer

composer require electrolinux/phpquery

Обновим composer

composer update

Для парсинга возьмем главную страницу Яндекса

В первом примере выведем всю страницу Яндекса, для этого в контроллере пишем следующий код

namespace app\controllers;

use Yii;
use GuzzleHttp\Client; // подключаем Guzzle
use yii\helpers\Url;

class YandexController extends \yii\web\Controller
{
    public function actionYandex {
        
        // создаем экземпляр класса
        $client = new Client();
        // отправляем запрос к странице Яндекса
        $res = $client->request('GET', 'http://www.yandex.ru');
        // получаем данные между открывающим и закрывающим тегами body
        $body = $res->getBody();
        // вывод страницы Яндекса в представление
        return $this->render('yandex', ['body' => $body]);
    }
}

Создадим файл-представление yandex.php и выведем страницу Яндекса

    echo $body;

Во втором примере выведем список новостей, для этого будем использовать phpQuery.

namespace app\controllers;

use Yii;
use GuzzleHttp\Client; // подключаем Guzzle
use yii\helpers\Url;

class YandexController extends \yii\web\Controller
{
    public function actionYandexnews {
        
        // создаем экземпляр класса
        $client = new Client();
        // отправляем запрос к странице Яндекса
        $res = $client->request('GET', 'http://www.yandex.ru');
        // получаем данные между открывающим и закрывающим тегами body
        $body = $res->getBody();
        // подключаем phpQuery
        $document = \phpQuery::newDocumentHTML($body);
        //Смотрим html страницы Яндекса, определяем внешний класс списка и считываем его командой find
        $news = $document->find(".b-news-list"); 
        // вывод списка новостей Яндекса с главной страницы в представление
        return $this->render('yandexnews', ['news' => $news]);
    }
}

Создадим файл-представление yandexnews.php и список новостей

    echo $news;

Пример третий. Выполним некоторые операции с полученными данными.

namespace app\controllers;

use Yii;
use GuzzleHttp\Client; // подключаем Guzzle
use yii\helpers\Url;

class YandexController extends \yii\web\Controller
{
    public function actionYandexnewslist {
        
        // создаем экземпляр класса
        $client = new Client();
        // отправляем запрос к странице Яндекса
        $res = $client->request('GET', 'http://www.yandex.ru');
        // получаем данные между открывающим и закрывающим тегами body
        $body = $res->getBody();
        // подключаем phpQuery
        $document = \phpQuery::newDocumentHTML($body);
        // получаем список новостей
        $news = $document->find("ul.b-news-list"); 
        // выполняем проход циклом по списку
        foreach ($news as $elem) {
            //pq аналог $ в jQuery
             $pq = pq($elem);
             // удалим первую новость в списке
             $pq->find('li.b-news-list__item:first')->remove();
             // выполним поиск в скиске ссылок
             $tags = $pq->find('li.b-news-list__item a');
             // добавим ковычки в начало и в конец предложения
             $tags->append('" ')->prepend(' "'); //
             // добавим свой класс к последней новости списка
             $pq->find('li.b-news-list__item:last')->addClass('my_last_class');
        }
        // вывод списка новостей яндекса с главной страницы в представление
        return $this->render('yandexnewslist', ['news' => $news]);
    }
}

Создадим файл-представление yandexnewslist.php и список новостей

    echo $news;

Это лишь малая часть возможностей phpQuery. Все возможные команды можно посмотреть на официальной странице phpQuery

Комментарии (5)

  1. Hik Vikulov 05 июня 2016, 20:25 # 0
    yii2 ругаеться на код! c2n.me/3yRByvK
    1. Игорь Костромин 05 июня 2016, 20:40 # 0
      подправил код, там переменная $body
      1. Артём Беляков 01 февраля 2017, 17:37 # 0
        А правильно ли это делать в контроллере? Я про MVC… Почти написал парсер, который считывает несколько спортивных событий, переходит по ссылкам этих событий и там ещё парсит статистику! И получился один огромный, преогромный контроллер… Вот это меня смущает! Как можно поступить в этом случае?
        1. Дмитрий Особый 03 мая 2017, 20:00 # -1
          Это потому, что пример был не о MVC
          Если делать все правильно то парсер это в модель…
          В YII по крайней мере так. Все что не контролер и не вьюшка это модель. По этому она супер пупер огромная обычно.
          Можно конечно дробить при потребности. К примеру поиск сейчас модно выносить отдельно.

          Да и GuzzleHttp ну каждый конечно как хочет… Мне больше нравится эта реализация github.com/linslin/Yii2-Curl
          1. Андрей Никитин 08 декабря 2017, 21:49 # 0
            Ну а почему нельзя было сразу нормально написать с моделями? Или люди должны догадываться что там подключать, и какие наследования должны идти??

        Вы должны авторизоваться, чтобы оставлять комментарии.

        Вы можете авторизоваться на сайте через:
        Vkontakte