Сейчас мы с вами изучим работу с XML. XML - это формат для обмена данными между сайтами. Он очень похож на HTML, только в XML разрешены свои теги и атрибуты.

Зачем нужен XML при парсинге? Иногда бывает так, что сайт, который вам нужно спарсить, имеет API, с помощью которого можно получить желаемое, особо не напрягаясь. Поэтому сразу совет - перед тем, как парсить сайт, проверьте, нету ли у него API.

Что такое API? Это набор функций, с помощью которых вы можете слать запрос этому сайту и получать нужный ответ. Вот этот ответ чаще всего приходит в формате XML. Поэтому давайте приступим к его изучению.

Работа с XML в PHP

Пусть у вас есть XML. Он может быть в строке, либо хранится в файле или отдаваться по запросу к определенному URL.

Пусть XML хранится в строке. В этом случае из этой строки нужно создать объект с помощью new SimpleXMLElement:

$str = "<?xml version='1.0'?>
<worker>
	<name>Коля</name>
	<age>25</age>
	<salary>1000</salary>
</worker>";

$xml = new SimpleXMLElement($str);

Сейчас у нас в переменной $xml хранится объект с разобранным XML. Обращаясь к свойствам этого объекта можно получать доступ с содержимому тегов XML. Как именно - разберем чуть ниже.

Если же XML хранится в файле или отдается по обращению к URL (что чаще всего и бывает), то следует использовать функцию simplexml_load_file, которая делает тот же объект $xml:

<?xml version='1.0'?>
<worker>
	<name>Коля</name>
	<age>25</age>
	<salary>1000</salary>
</worker>
$xml = simplexml_load_file(путь к файлу или урл);

Приемы работы

В примерах ниже наш XML хранится в файле или по URL.

Пусть дан следующий XML:

<?xml version='1.0'?>
<worker>
	<name>Коля</name>
	<age>25</age>
	<salary>1000</salary>
</worker>

Давайте получим имя, возраст и зарплату работника:

$xml = simplexml_load_file(путь к файлу или урл);
echo $xml->name; //выведет 'Коля'
echo $xml->age; //выведет 25
echo $xml->salary; //выведет 1000

Как вы видите, у объекта $xml есть свойства, соответствующие тегам.

Вы может обратили внимание, что тег <worker> нигде не фигурирует при обращении. Это потому, что он корневой тег. Можно переименовать его, например, на <root> - и ничего не поменяется:

<?xml version='1.0'?>
<root>
	<name>Коля</name>
	<age>25</age>
	<salary>1000</salary>
</root>
$xml = simplexml_load_file(путь к файлу или урл);
echo $xml->name; //выведет 'Коля'
echo $xml->age; //выведет 25
echo $xml->salary; //выведет 1000

Корневой тег в XML может быть только один, так же, как и тег <html> в обычном HTML.

Давайте чуть модифицируем наш XML:

<?xml version='1.0'?>
<root>
	<worker>
		<name>Коля</name>
		<age>25</age>
		<salary>1000</salary>
	</worker>
</root>

В этом случае у нас получится цепочка обращений:

$xml = simplexml_load_file(путь к файлу или урл);
echo $xml->worker->name; //выведет 'Коля'
echo $xml->worker->age; //выведет 25
echo $xml->worker->salary; //выведет 1000

Работа с атрибутами

Пусть некоторые данные хранятся в атрибутах:

<?xml version='1.0'?>
<root>
	<worker name="Коля" age="25" salary="1000">Номер 1</worker>
</root>
$xml = simplexml_load_file(путь к файлу или урл);
echo $xml->worker['name']; //выведет 'Коля'
echo $xml->worker['age']; //выведет 25
echo $xml->worker['salary']; //выведет 1000
echo $xml->worker; //выведет 'Номер 1'

Теги с дефисами

В XML разрешены теги (и атрибуты) с дефисом. В этом случае обращение к таким тегам происходит так:

<?xml version='1.0'?>
<root>
	<worker>
		<first-name>Коля</first-name>
		<last-name>Иванов</last-name>
	</worker>
</root>
$xml = simplexml_load_file(путь к файлу или урл);
echo $xml->worker->{first-name}; //выведет 'Коля'
echo $xml->worker->{last-name}; //выведет 'Иванов'

Перебор циклом

Пусть теперь у нас не один работник, а несколько. В этом случае мы можем перебрать наш объект с помощью цикла foreach:

<?xml version='1.0'?>
<workers>
	<worker>
		<name>Коля</name>
		<age>25</age>
		<salary>1000</salary>
	</worker>
	<worker>
		<name>Вася</name>
		<age>26</age>
		<salary>2000</salary>
	</worker>
	<worker>
		<name>Петя</name>
		<age>27</age>
		<salary>3000</salary>
	</worker>
</workers>
$xml = simplexml_load_file(путь к файлу или урл);

foreach ($xml as $worker) {
	echo $worker->name; //выведет 'Коля', 'Вася', 'Петя'
}

Из объекта в нормальный массив

Если вам неудобно работать с объектом, вы можете преобразовать его в нормальный массив PHP с помощью следующего хитрого приема:

$xml = simplexml_load_file(путь к файлу или урл);

var_dump(json_decode(json_encode($xml), true));

Больше информации

Смотрите также документацию SimpleXML.

Парсинг на основе sitemap.xml

Зачастую на сайте есть файл sitemap.xml. В этом файле хранятся ссылки на все страницы сайта для удобства индексации их поисковыми системами (индексация - это по сути и есть парсинг сайта яндексом и гуглом).

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

Как проверить наличие этого файла: пусть мы парсим сайт site.ru, тогда обратитесь в браузере к site.ru/sitemap.xml - если что-то увидите, значит он там есть, а если не увидите - то увы.

Если sitemap есть - то в нем содежатся ссылки на все страницы сайта в формате XML. Спокойно забираете этот XML, парсите его, отделяете ссылки на нужные вам страницы любым удобным вам способом (например, анализом URL, который был описан в методе паука).

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

Подробнее об устройстве sitemap.xml читайте в википедии.