Комментарии 39
Сдаётся мне, что большая часть задач просто решается с использованием штатного DOMXPath и, вероятнее всего, заметно быстрее. Да, синтаксис не как у CSS селекторов, но не намного сложнее. Потому библиотека, созданная 10 лет назад, и не обрела себе новой жизни.
Согласен. Но не каждый будет париться с DOMХpath, когда есть сиюминутное решение. Хотя я полностью поддерживаю изучение встроенной библиотеки. У неё, в отличии от phpQuery, есть какое-то будущее.
pq($value)
ужасно бесит, особенно, если нужно парсить вложенные элементы. DiDom гораздо удобнее для этогоесть symfony/dom-crawler, который враппер для стандартной DOM библиотеки. И с помощью symfony/css-selector можно писать в без XPath, оно само конвертирует.
Только вдобавок в отличии от phpQuery оно еще и написано не на статических свойствах, которые хранят хрен пойми, включая прошлые документы и не течет как соломенная крыша.
// Получаем код $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(); }
а можно было вот так:
$html = file_get_contents("https://какой-то_сайт.com/");
$crawler = (new Crawler($html));
$productHref = $crawler->filter('.product-essential')->each($node) {
return [
'brand-href' => $node->filter('.brand-link')->first()->attr('href'),
'brand-name' => $node->filter('.brand-name')->first()->text(),
'product-name' => $node->filter('.product-name h1')->first()->text(),
'product-price' => $node->filter('.price-info .price-box .regular-price .price')->text(),
'product-description' => $node->filter('.description .product-description')->text(),
'product-id' => $node->filter('.description .sku span')->eq(1)->text(),
];
});
Сильно сложно?
Начнем с того, что пользоваться Symfony — уже огромная проблема. Сомневаюсь, что кто-то будет собирать маленький проект на Symfony. Да, согласен, есть новые библиотеки. Одну из них я в статье указал. Но, как мне кажется, phpQuery одна из самых легких для понимания.
Может быть я легко отношусь к маленьким проектам, но разворачивать композер, подтягивать через него библиотеки. Немного наворочено. Хотя идея, соглашусь, здравая.
Замечательно. Давайте упакуем все это в докер, и, для полноты картины, будем следить за актуальностью БД с помощью доктрины. Тогда проект будет максимально удобным и максимально усложненным.
Повторюсь, я за использование актуальных библиотек. Но если уж кто-то услышал про phpQuery (а слышат о нем сейчас только новички, либо вспоминают старички), то почему бы не выдать нормальное объяснение с примером?
А потом эти люди спустятся в комментарии, увидят ваше объяснение про Crawler, заинтересуются им. Будут разворачивать замечательные проекты. Сплошные плюсы же.
вот вы любите все усложнять:)
тут к чему ведут, так это что установка пакета композером нисколько не тяжелей скачивания библиотеки руками.
три строки а консоли (хоть в linux, хоть в каком-нибудь OpenServer под windows) и можно начинать накидывать код. даже если представить что у кого-то еще остался шаред хост, без консоли и вот этого вот всего, то вам же все равно закидывать туда проект по какому-нибудь ftp, так какая разница это папка vendor или phpQuery? и какая разница, будете ли вы писать require 'vendor/autoload.php' в своём скрипте или require 'phpQuery/phpQuery.php'?
Но если уж кто-то услышал про phpQuery (а слышат о нем сейчас только новички, либо вспоминают старички), то почему бы не выдать нормальное объяснение с примером?
Потому что не надо уже. Есть более актуальные и изящные решения для ровно тех же задач.
Зачем новичкам открывать мир старого? Куда лучше учить их сразу хорошим практикам
mkdir myproject
cd myproject
wget https://getcomposer.org/composer.phar
php composer.phar require symfony/dom-crawler
php composer.phar require symfony/css-selector
если использовать phpquery его же тоже надо скачать, разархивировать, подключить.
То есть что я хочу сказать что Композер это не утяжеляет проект ни разу.
Я же не против. Ни разу, правда, так не делал.
myproject$ find . | wc -l
120
Всего лишь 120 файлов ради dom-crawler.
$ find . -type f | wc -l
и 98
Для крупного проекта dom-crawler выглядит очень даже привлекательно. Но для какого-нибудь однофайлового инструмента я бы не рискнул использовать.
Честно говоря, очень надеялся что пара строк
php composer.phar require symfony/dom-crawler
php composer.phar require symfony/css-selector
притянет 3-5 файлов, но получилось сильно больше, чем я ожидал.
В любой из этих папок можно поселить бэкдор.
Приличные люди папкой вендора в интернет не светят.
Может быть, несущественно, но каждый файл и папка тратят inode.
у меня на сервере лежит более 3 миллионов картинок и пока инод хватает.
довольно плохо представляю себе какое количество проектов нужно держать, чтоб они закончились, но на такой случай есть phar и готовые инструменты, которые сами соберут composer проект в исполняемый файл. например, github.com/clue/phar-composer
phpQuery одна из самых легких для понимания.
очень субъективно.
на насколько, по-вашему, мой код вышел сложнее того, что вы привели в статье?
а еще она одна из самых тяжелых для исполнения. она тормозит и течет из всех щелей. попробуйте обойти несколько тысяч страниц.
Symfony это в первую очередь набор компонентов, а уж потом фреймворк. Вы всегда можете установить symfony/dom-crawler
не устанавливая все остальное
Но, какая разница, если работает?
(new Crawler($html))
->filter('.classname')
->first()
->attr('id')
PS: Про удобство DomCrawler конечно же имею ввиду вкупе с css-selector пакетом
Потребления памяти (в байтах)
Максимальное
Nokogiri — 763568
DiDom — 793096
Zend Dom — 954712
DomCrawler — 1534512
Simple HTML DOM — 16839400
В конце теста
Nokogiri — 157168
DiDom — 158896
Zend Dom — 329232
DomCrawler — 567440
Simple HTML DOM — 14113456
Затраченное время (в секундах)
DiDom — 27.0787
Nokogiri — 27.1009
DomCrawler — 36.0982
Zend Dom — 48.3222
Simple HTML DOM — 188.0247
1 в поисковиках вылазит в большом количестве Simple. Но он протекает и медленный.
Function create_function() is deprecated in /phpquery/phpQuery/phpQuery/phpQueryObject.php
В общем нет, спасибо, не надо.
Снова про phpQuery