Pull to refresh

Снова про phpQuery

PHP *jQuery *
Sandbox
Приветствую всех. Недавно я взял заказ, где нужно было автоматически подтягивать данные на сайт (проще говоря — написать парсер).

Содержание статьи:



Предисловие


Так как я работаю на php, то мой взор пал на библиотеку phpQuery. Я, конечно, соглашусь, что есть множество других библиотек, в том числе и встроенная в php по умолчанию, но для рядового программиста, который подрабатывает фрилансом на выходных, нужно некое чудо. К счастью, всеми нами движет лень. Одного чеха лень привела к созданию phpQuery.

Документации на русском языке к данной библиотеке я не нашел (может быть плохо искал?). Найдя кучу вопросов от новичков на форумах, и не имея возможности прочитать документацию на английском, я задумался о написании этой статьи. Прошу учесть, что статья написана, в основном, для новичков.

Приступим


PhpQuery не самая быстрая библиотека, но одна из. С новыми версиями php она почти незаметна. Основная нагрузка, как и раньше, ложится на подгрузку страниц.
У неё полно возможностей, о которых не говорится во многих русскоязычных руководствах.
Некоторые программисты, так и не разобравшись с phpQuery, бегут создавать собственные библиотеки (прямо как наши коллеги из мира js). Да, у этой библиотеки есть главный недостаток — код устарел, но вполне себе работает.

Начало работы


Новичкам довольно сложно сходу понять работу phpQuery. Но я постараюсь максимально «разжевать» все сложные моменты.

Многие методы это библиотеки нацелены на работу с Dom, как будто мы работаем на jQuery. Да и названия у данных библиотек максимально похожи.

И так. Для начала нам нужно определиться с сайтом, с которого мы будем забирать HTML код. К слову, это не обязательно должен быть сайт. Если у нас уже есть html (xml) в файле (переменной), то можем подгрузить и оттуда.

/**
Если сайт:
$siteName = "site.com/";

Если файл: 
$siteName = "index.html";
*/

$html = file_get_contents("$siteName");

Далее нам нужно передать полученный код обработчику phpQuery

$dom = phpQuery::newDocument($html);

Метод «newDocument()» вернет dom объект, с которым мы можем работать.

Теперь мы можем что-то найти в этом dom объекте. Давайте представим, что мы подтягиваем страничку сайта, где есть такой блок:

<div class="product-essential">
    <a class="brand-link" href="https://какой-то_сайт.com/какой-то_бренд" title="Какой-то бренд">
        <span class="brand-name">Какой-то бренд</span>
    </a>
    <div class="product-name">
        <h1>Jeans Denim</h1>
    </div>
    <div class="price-info">
        <div class="price-box">
                <span class="regular-price" id="product-price-424337">
                    <span class="price">€ 200</span>
                </span>
        </div>
    </div>
    <div class="description">
        <span class="product-description">Описание товара</span>
        <div class="sku">
            <span> ID продукта:</span>
            <span>830214303</span>
        </div>
    </div>
</div>

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

Практическая часть


Попробуем получить все вышеперечисленные данные.

// Получаем код
$html = file_get_contents("https://какой-то_сайт.com/");

// Получаем объект dom
$dom = phpQuery::newDocument($html);

// Ищем в объекте dom элемент с классом .product-essential, обращаясь к методу find(). Он вмещает в себя все данные о продукте.
foreach($dom->find(".product-essential") as $key => $value){

        // Преобразуем dom объект в объект phpQuery. Делаем сие действие с помощью метода pq(); который является аналогом ($) в jQuery.
    $pq = pq($value);

    // Находим в этом элементе элемент с классом .brand-link и получаем значение атрибута "href" с помощью метода attr();
    $productHref[$key]["brand-href"] = $pq->find(".brand-link")->attr("href");

    // Получаем название бренда. Оно находится в строке <span class="brand-name">Какой-то бренд</span>.
    // Мы можем получить текст, содержащийся в <span> и других тегах с помощью метода text();
    $productHref[$key]["brand-name"] = $pq->find(".brand-name")->text();

    // Далее нам необходимо получить название товара.
    // Помимо указания класса элемента, мы можем указать имя вложенного элемента.
    // В данном случае имя бренда находится в элементе <h1>, который находится в элементе <div class="brand-name">
    $productHref[$key]["product-name"] = $pq->find(".product-name h1")->text();

    // PhpQuery позволяет перечислять классы нескольких, вложенных друг в друга, элементов.
    // Только не забывайте следить за порядком!
    // Тут мы получаем цену товара.
    $productHref[$key]["product-price"] = $pq->find(".price-info .price-box .regular-price .price")->text();

    // Получаем описание товара
    $productHref[$key]["product-description"] = $pq->find(".description .product-description")->text();

    // Так же есть возоможность шагать по элементам.
    // Деется это с помощью метода next();
    // В данном случае мы получим только числовой идентификатор без лишних строк.
    $productHref[$key]["product-id"] = $pq->find(".description .sku span")->next()->text();
    
}

На выходе получаем вот такой массив:

Array
(
    [0] => Array
        (
            [brand-href] => https://какой-то_сайт.com/какой-то_бренд
            [brand-name] => Какой-то бренд
            [product-name] => Jeans Denim
            [product-price] => € 200
            [product-description] => Описание товара
            [product-id] => 830214303
        )

)

Заключение


PhpQuery очень удобная библиотека, но, к сожалению, слишком тяжелая. Так что после прохода по элементам рекомендуется выгружать документ:

phpQuery::unloadDocuments();

Несмотря на удобство библиотеки, советую к ней не привыкать. Для решения мелких задач она подходит, наверное, лучше всех. Но это все же немного устаревшая библиотека.

В этой библиотеке есть возможность добавлять элементы «на лету». Но эту тему мы затронем в следующей статье.
Tags:
Hubs:
Total votes 17: ↑11 and ↓6 +5
Views 24K
Comments Comments 39