Я думаю, вы уже прочувствовали неудобство регулярок на себе. Все-таки, они не очень удобны для разбора HTML кода. Поэтому существуют специальные библиотеки, позволяющие упростить разбор HTML. Их представителем является phpQuery, которую мы сейчас и разберем (остальные библиотеки изучим попозже).

Почему мы начинаем с phpQuery? Потому что она имитирует библиотеку jQuery, с которой многие хорошо знакомы. Вместо того, чтобы писать сложные регулярки для получения блоков сайта, с помощью phpQuery мы сможем обращаться к ним с помощью селекторов CSS (если вы плохо владеете ими - изучите их по ссылке).

Сразу предупреждаю, что данная библиотека представляет собой класс и для того, чтобы понять работу с нею, вам нужно владеть хотя бы минимумом знаний по ООП. Если вы его не знаете - изучите его по ссылке ООП в PHP и только потом продолжите чтение.

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

Официальная документация (англ.) находится по ссылке http://code.google.com/archive/p/phpquery/. Зайдите туда, скачайте эту библиотеку, положите в папку со своим проектом и подключите ее вот так:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';
?>

Начало положено, давайте теперь приступим к освоению этой библиотеки.

Основы работы с phpQuery

Работа с phpQuery происходит подобно jQuery (те же методы). Впрочем, даже не зная jQuery вам будет легко разобраться (или же просто возьмите мои заготовки кода и используйте их, особо не вникая).

Итак, начало работы с библиотекой начинается с phpQuery::newDocument($str), где переменная $str - это HTML код для разбора. В результате вернется объект, к которому мы сможем применять определенные методы:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<div id="elem">Текст</div><div>Еще тег</div>';
	$pq = phpQuery::newDocument($str);
?>

Итак, в переменной $pq лежит объект. У этого объекта есть метод find, который параметром принимает CSS селектор, а делает следующее: ищет внутри HTML кода из $pq элементы подпадающие под этот селектор. Пример:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<div id="elem">Текст</div><div>Еще тег</div>';
	$pq = phpQuery::newDocument($str);

	$elem = $pq->find('#elem');
?>

Сейчас в переменной $elem лежит объект с найденным дивом #elem. У этого объекта есть метод html, который выводит текст найденного элемента (в нашем случае текст дива #elem):

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<div id="elem">Текст</div><div>Еще тег</div>';
	$pq = phpQuery::newDocument($str);

	$elem = $pq->find('#elem');
	$text = $elem->html();
	var_dump($text);
?>

Кроме метода html есть еще метод text, который делает почти то же самое. Разница: если внутри нашего дива были бы другие теги - метод html вернул бы его текст вместе с этими тегами, а метод text - без них (как будто бы строку обработали функцией strip_tags).

Получение атрибутов

Кроме содержимого тегов, можно также получать содержимое атрибутов. Это делает метод attr, параметром принимающий название атрибута. Давайте получим содержимое href ссылки:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<a id="elem" href="http://google.com">Ссылка</a>';
	$html = phpQuery::newDocument($str);
	$pq = pq($html);

	$elem = $pq->find('#elem');
	$href = $elem->attr('href');
	var_dump($href);
?>

Работа с набором элементов

Предположим, что мы хотим получить не один элемент по его id, а несколько. Давайте попробуем сделать так:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<a href="1.html">1</a><a href="2.html">2</a><a href="3.html">3</a>';
	$pq = phpQuery::newDocument($str);

	$links = $pq->find('a');
	$text = $links->html();
	var_dump($text);
?>

В результате мы увидим строку '123' - содержимое трех ссылок слитое в одну строку. Врядли мы хотели получить именно это - нам наверняка хотелось бы иметь массив текстов ссылок и массив их href.

Давайте посмотрим на следующий код:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<a href="1.html">1</a><a href="2.html">2</a><a href="3.html">3</a>';
	$pq = phpQuery::newDocument($str);

	$links = $pq->find('a');
?>

В данном случае переменная $links - объект, состоящий из набора других объектов. Такие объекты можно перебирать циклом foreach - и это будет работать. Вот так:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<a href="1.html">1</a><a href="2.html">2</a><a href="3.html">3</a>';
	$pq = phpQuery::newDocument($str);

	$links = $pq->find('a');

	foreach ($links as $link) {

	}
?>

Внутри цикла переменная $link будет объектом, однако не объектом phpQuery, а объектом DOM. Это значит, что к $link не применимы методы phpQuery (в частности find и html). Чтобы сделать из него объект phpQuery, его следует обернуть в функцию pq (аналог доллара в jQuery).

Давайте сделаем это и заодно накопим тексты ссылок и их href в отдельные массивы:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<a href="1.html">1</a><a href="2.html">2</a><a href="3.html">3</a>';
	$pq = phpQuery::newDocument($str);

	$links = $pq->find('a');

	foreach ($links as $link) {

		$pqLink = pq($link); //pq делает объект phpQuery

		$text[] = $pqLink->html();
		$href[] = $pqLink->attr('href');
	}

	var_dump($text);
	var_dump($href);
?>

Удаление

С помощью phpQuery можно удалять по селектору мешающие вам элементы. Это делается с помощью метода remove. Смотрите пример:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<div id="elem">Текст</div><div>Еще тег</div>';
	$pq = phpQuery::newDocument($str);

	$elem = $pq->remove('#elem');
	$text = $pq->html();
	var_dump($text);
?>

В результате блок <div id="elem">Текст</div> удалится и в строке останется <div>Еще тег</div>.

Оборачивание

Можно также оборачивать элементы с помощью метода wrap. Смотрите пример:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<a id="elem">Ссылка</a><div>Еще тег</div>';
	$pq = phpQuery::newDocument($str);

	$elem = $pq->find('#elem')->wrap('<div>');
	$text = $pq->html();
	var_dump($text);
?>

В результате ссылка обернется в див и станет выглядеть так: <div><a id="elem">Ссылка</a></div>.

Оборачивание

... Смотрите пример:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<a id="elem">Ссылка</a><div>Еще тег</div>';
	$pq = phpQuery::newDocument($str);

	$elem = $pq->find('#elem')->wrap('<div class="www">');
	$text = $pq->html();
	var_dump($text);
?>

В результате ... и станет выглядеть так: <div class="www"><a id="elem">Ссылка</a></div>.

Оборачивание внутри

... Смотрите пример:

<?php
	require_once 'phpQuery/phpQuery/phpQuery.php';

	$str = '<a id="elem">Ссылка</a><div>Еще тег</div>';
	$pq = phpQuery::newDocument($str);

	$elem = $pq->find('#elem')->wrapInner('<b>');
	$text = $pq->html();
	var_dump($text);
?>

В результате ... и станет выглядеть так: <a id="elem">Ссылка</a>.

replaceWith

prev, next, siblings

prevAll, nextAll

prevUntil, nextUntil

parents

псевдоклассы :not, :has, :contains :first, :last, :eq, :empty

Больше возможностей

В общем, phpQuery умеет многое из того, что умеет jQuery и это очень полезно при парсинге. Хорошо владея jQuery, вы сможете понимать и использовать все богатые возможности phpQuery.

Поэтому еще раз рекомендую внимательно изучить учебник jQuery.

Полные возможности phpQuery по манипулированию с DOM смотрите по этой ссылке.

Полные возможности phpQuery по перемещению по дереву DOM смотрите по этой ссылке.

Использование селекторов и псевдоклассов jQuery смотрите по этой ссылке.