PHP Simple HTML DOM Parser Manual
// Find all article blocks
foreach($html->find( ‘div.article’ ) as $article) $item[ ‘title’ ] = $article->find( ‘div.title’ , 0 )->plaintext;
$item[ ‘intro’ ] = $article->find( ‘div.intro’ , 0 )->plaintext;
$item[ ‘details’ ] = $article->find( ‘div.details’ , 0 )->plaintext;
$articles[] = $item;
>
How to create HTML DOM object?
// Create a DOM object from a string
$html = str_get_html( ‘
// Create a DOM object from a URL
$html = file_get_html( ‘http://www.google.com/’ );
// Create a DOM object from a HTML file
$html = file_get_html( ‘test.htm’ );
// Create a DOM object
$html = new simple_html_dom();
// Load HTML from a string
$html->load( ‘
// Load HTML from a URL
$html->load_file( ‘http://www.google.com/’ );
// Load HTML from a HTML file
$html->load_file( ‘test.htm’ );
How to find HTML elements?
// Find all anchors, returns a array of element objects
$ret = $html->find( ‘a‘ );
// Find (N)th anchor, returns element object or null if not found (zero based)
$ret = $html->find( ‘a‘, 0 );
// Find lastest anchor, returns element object or null if not found (zero based)
$ret = $html->find( ‘a‘, -1 );
// Find all with the id attribute
$ret = $html->find( ‘div[id]‘ );
// Find all which attribute id=foo
$ret = $html->find( ‘div[id=foo]‘ );
// Find all element which id=foo
$ret = $html->find( ‘#foo‘ );
// Find all element which class=foo
$ret = $html->find( ‘.foo‘ );
// Find all element has attribute id
$ret = $html->find( ‘*[id]‘ );
// Find all anchors and images
$ret = $html->find( ‘a, img‘ );
// Find all anchors and images with the «title» attribute
$ret = $html->find( ‘a[title], img[title]‘ );
Supports these operators in attribute selectors:
Filter | Description |
---|---|
[attribute] | Matches elements that have the specified attribute. |
[!attribute] | Matches elements that don’t have the specified attribute. |
[attribute=value] | Matches elements that have the specified attribute with a certain value. |
[attribute!=value] | Matches elements that don’t have the specified attribute with a certain value. |
[attribute^=value] | Matches elements that have the specified attribute and it starts with a certain value. |
[attribute$=value] | Matches elements that have the specified attribute and it ends with a certain value. |
[attribute*=value] | Matches elements that have the specified attribute and it contains a certain value. |
$es = $html->find( ‘ul li‘ );
// Find Nested tags
$es = $html->find( ‘div div div‘ );
// Find all td tags with attribite align=center in table tags
$es = $html->find( »table td[align=center]‘ );
// Find all text blocks
$es = $html->find( ‘text‘ );
// Find all comment () blocks
$es = $html->find( ‘comment‘ );
foreach($html->find( ‘ul‘ ) as $ul)
foreach($ul->find( ‘li‘ ) as $li)
// do something.
>
>
How to access the HTML element’s attributes?
// Get a attribute ( If the attribute is non-value attribute (eg. checked, selected. ), it will returns true or false)
$value = $e->href;
// Set a attribute(If the attribute is non-value attribute (eg. checked, selected. ), set it’s value as true or false)
$e->href = ‘my link’ ;
// Remove a attribute, set it’s value as null!
$e->href = null ;
// Determine whether a attribute exist?
if(isset($e->href))
echo ‘href exist!’ ;
// Example
$ html = str_get_html ( «
» ) ;
$e = $html->find( «div» , 0 );
echo $e->tag; // Returns: » div»
echo $e->outertext; // Returns: »
»
echo $e->innertext; // Returns: » foo bar»
echo $e->plaintext; // Returns: » foo bar«
Attribute Name | Usage |
---|---|
$e->tag | Read or write the tag name of element. |
$e->outertext | Read or write the outer HTML text of element. |
$e->innertext | Read or write the inner HTML text of element. |
$e->plaintext | Read or write the plain text of element. |
// Extract contents from HTML
echo $html->plaintext;
// Wrap a element
$e->outertext = » . $e->outertext . ‘ ‘;
// Remove a element, set it’s outertext as an empty string
$e->outertext = » ;
// Append a element
$e->outertext = $e->outertext . ‘foo ‘;
// Insert a element
$e->outertext = ‘foo ‘ . $e->outertext;
How to traverse the DOM tree?
// If you are not so familiar with HTML DOM, check this link to learn more.
// Example
echo $html->find( «#div1», 0 )->children( 1 )->children( 1 )->children( 2 )-> id ;
// or
echo $html->getElementById( «div1» )->childNodes( 1 )->childNodes( 1 )->childNodes( 2 )->getAttribute( ‘id’ );
Получение элементов DOM по имени класса
Я использую PHP DOM и пытаюсь получить элемент в узле DOM, который имеет заданное имя класса. Какой лучший способ получить этот подэлемент?
Ответ 1
Итак, PHP будет таким:
$dom = new DomDocument();
$dom->load($filePath);
$finder = new DomXPath($dom);
$classname=»my-class»;
$nodes = $finder->query(«//*[contains(concat(‘ ‘, normalize-space(@class), ‘ ‘), ‘ $classname ‘)]»);
По сути, все, что мы здесь делаем, — это нормализуем атрибут class так, чтобы даже один класс был ограничен пробелами, а полный список классов был ограничен пробелами. Затем добавляем к искомому классу пробел. Таким образом, мы эффективно ищем и находим только экземпляры my-class. Использовать селектор xpath?
$dom = new DomDocument();
$dom->load($filePath);
$finder = new DomXPath($dom);
$classname=»my-class»;
$nodes = $finder->query(«//*[contains(@class, ‘$classname’)]»);
Если это только один тип элемента, вы можете заменить «*» на конкретное название.
Если вам нужно сделать много подобных действий с очень сложными селекторами, я бы рекомендовал Zend_Dom_Query, который поддерживает синтаксис CSS-селекторов (то есть jQuery):
$finder = new Zend_Dom_Query($html);
$classname = ‘my-class’;
$nodes = $finder->query(«*[class~=\»$classname\»]»);
Ответ 2
Если вы хотите получить innerhtml класса без zend, вы можете использовать это:
$dom = new DomDocument();
$dom->load($filePath);
$classname = ‘main-article’;
$finder = new DomXPath($dom);
$nodes = $finder->query(«//*[contains(concat(‘ ‘, normalize-space(@class), ‘ ‘), ‘ $classname ‘)]»);
$tmp_dom = new DOMDocument();
foreach ($nodes as $node)
$tmp_dom->appendChild($tmp_dom->importNode($node,true));
>
$innerHTML.=trim($tmp_dom->saveHTML());
echo $innerHTML;
Ответ 3
Я думаю, что принятый способ лучше, но мне кажется , что это тоже может сработать:
function getElementByClass(&$parentNode, $tagName, $className, $offset = 0)
$response = false;
$childNodeList = $parentNode->getElementsByTagName($tagName);
$tagCount = 0;
for ($i = 0; $i < $childNodeList->length; $i++)
$temp = $childNodeList->item($i);
if (stripos($temp->getAttribute(‘class’), $className) !== false)
if ($tagCount == $offset)
$response = $temp;
break;
>
$tagCount++;
>
>
return $response;
>
Ответ 4
Существует также другой подход, не требующий использования DomXPath или Zend_Dom_Query. Основываясь на оригинальной функции dav, я написал следующую функцию, которая возвращает все дочерние узлы родительского узла, чьи тег и класс соответствуют заданным параметрам.
function getElementsByClass(&$parentNode, $tagName, $className)
$nodes=array();
$childNodeList = $parentNode->getElementsByTagName($tagName);
for ($i = 0; $i < $childNodeList->length; $i++)
$temp = $childNodeList->item($i);
if (stripos($temp->getAttribute(‘class’), $className) !== false)
$nodes[]=$temp;
>
>
return $nodes;
>
Предположим, что у вас есть переменная $html, содержащая следующий HTML:
Я нахожусь в узле содержимого.
Я нахожусь в узле содержимого.
Я нахожусь в узле содержимого.
Я нахожусь в узле нижнего колонтитула.
Использовать getElementsByClass очень просто:
$dom = new DOMDocument(‘1.0’, ‘utf-8’);
$dom->loadHTML($html);
$content_node=$dom->getElementById(«content_node»);
$div_a_class_nodes=getElementsByClass($content_node, ‘div’, ‘a’); //будет содержать три узла под «content_node».
Ответ 5
Нативная обработка DOM в PHP настолько абсурдно плоха, что сделайте себе одолжение и используйте этот или любой другой современный пакет для разбора HTML, который может справиться с этим в несколько строк , — у становите paquettg/php-html-parser с помощью:
composer require paquettg/php-html-parser
Затем создайте файл .php в той же папке с таким содержанием:
// загружаем зависимости через Composer
require __DIR__ . ‘/vendor/autoload.php’;
use PHPHtmlParser\Dom;
$dom = new Dom;
$dom->loadFromUrl(«https://example.com»);
$links = $dom->find(‘.classname a’);
foreach ($links as $link)
echo $link->getAttribute(‘href’);
>
Информацию о том, как установить Composer, вы найдете на домашней странице Composer.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
PHP HTML DOM парсер с jQuery подобными селекторами
Добрый день, уважаемые хабровчане. В данном посте речь пойдет о совместном проекте S. C. Chen и John Schlick под названием PHP Simple HTML DOM Parser (ссылки на sourceforge).
Идея проекта — создать инструмент позволяющий работать с html кодом используя jQuery подобные селекторы. Оригинальная идея принадлежит Jose Solorzano’s и реализована для php четвертой версии. Данный же проект является более усовершенствованной версией базирующейся на php5+.
В обзоре будут представлены краткие выдержки из официального мануала, а также пример реализации парсера для twitter. Справедливости ради, следует указать, что похожий пост уже присутствует на habrahabr, но на мой взгляд, содержит слишком малое количество информации. Кого заинтересовала данная тема, добро пожаловать под кат.
Получение html кода страницы
$html = file_get_html('http://habrahabr.ru/'); //работает и с https://
Товарищ Fedcomp дал полезный комментарий насчет file_get_contents и 404 ответа. Оригинальный скрипт при запросе к 404 странице не возвращает ничего. Чтобы исправить ситуацию, я добавил проверку на get_headers. Доработанный скрипт можно взять тут.
Поиск элемента по имени тега
foreach($html->find('img') as $element) < //выборка всех тегов img на странице echo $element->src . '
'; // построчный вывод содержания всех найденных атрибутов src >
Модификация html элементов
$html = str_get_html('HelloWorld'); // читаем html код из строки (file_get_html() - из файла) $html->find('div', 1)->class = 'bar'; // присвоить элементу div с порядковым номером 1 класс "bar" $html->find('div[id=hello]', 0)->innertext = 'foo'; // записать в элемент div с текст foo echo $html; // выведет fooWorld
Получение текстового содержания элемента (plaintext)
echo file_get_html('http://habrahabr.ru/')->plaintext;
Целью статьи не является предоставить исчерпывающую документацию по данному скрипту, подробное описание всех возможностей вы можете найти в официальном мануале, если у сообщества возникнет желание, я с удовольствием переведу весь мануал на русский язык, пока же приведу обещанный в начале статьи пример парсера для twitter.
Пример парсера сообщений из twitter
require_once 'simple_html_dom.php'; // библиотека для парсинга $username = 'habrahabr'; // Имя в twitter $maxpost = '5'; // к-во постов $html = file_get_html('https://twitter.com/' . $username); $i = '0'; foreach ($html->find('li.expanding-stream-item') as $article) < //выбираем все li сообщений $item['text'] = $article->find('p.js-tweet-text', 0)->innertext; // парсим текст сообщения в html формате $item['time'] = $article->find('small.time', 0)->innertext; // парсим время в html формате $articles[] = $item; // пишем в массив $i++; if ($i == $maxpost) break; // прерывание цикла >
Вывод сообщений
for ($j = 0; $j < $maxpost; $j++) < echo ''; echo '' . $articles[$j]['text'] . '
'; echo '' . $articles[$j]['time'] . '
'; echo ''; >
Благодарю за внимание. Надеюсь, получилось не очень тяжеловесно и легко для восприятия.
Похожие библиотеки
P.S.
Хаброжитель Groove подсказал что подобные материалы уже были
P.P.S.
Постараюсь в свободное время собрать все библиотеки и составить сводные данные по производительности и приятности использования.