Телефон: +7 (926) 245-03-63

Парсинг HTML на PHP

Следующая статья: Что такое PHP?

Потихоньку изучаю возможности PHP для создания парсеров. Я уже писала о том, как парсить xml на php с помощью SimpleXML. Сейчас расскажу об одном из способов парсинга html (он подойдет и для xml тоже, кстати). Повторю, что в php я не гуру, поэтому буду очень признательна, если вы оставите свои комментарии к поднятой теме.

Побродив по нашим и англоязычным форумам, поняла, что спор о том, лучше ли парсить html регулярными выражениями или использовать для этих целей возможности PHP DOM, является холиваром. Сама же я пришла к выводу, что все зависит от сложности структуры данных. Ведь если структура достаточно сложная, то с помощью регулярок приходится парсить в несколько этапов: сначала выделить большой кусок, потом разделить его на более маленькие и так далее.. В итоге, если данные сложные (или их очень много), то процесс парсинга может значительно затянуться. Ресурсоемкость в этом случае еще будет зависеть, конечно же, от самих регулярных выражений. Если в регэкспах много «.*» (они являются самыми ресурсоемкими, так как «прочесывают» исходный код с максимальной жадностью), то замедление будет заметным.

И вот как раз в этом-то случае как нельзя кстати приходится PHP DOM. Это удобный инструмент для парсинга как XML, так и HTML. Некоторые придерживаются мнения, что парсить html регэкспами вообще нельзя, и яростно защищают PHP DOM.

В свою очередь я ознакомилась с этим расширением, написав простенький скрипт. Который и привожу здесь, чтобы наглядно показать, как это все легко и просто. В примере разбирается html с частью карты сайта этого блога. Он присвоен переменной прямо внутри кода. В «боевых» же условиях исходные данные следует получать, например, через file_get_contents().

<?php
$html = '
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<head>
<title>Parsing-and-i.blogspot.com Map</title>
</head>
<body>
<h2>Последние темы блога</h2>
<!-- на 09.08.2009 -->
<table>
<tr>
<td>
<a href="http://parsing-and-i.blogspot.com/2009/08/blog-post_06.html">
http://parsing-and-i.blogspot.com/2009/08/blog-post_06.html</a>
</td>
<td>Базы</td>
</tr>
<tr>
<td>
<a href="http://parsing-and-i.blogspot.com/2009/08/mysql-delphi-express.html">
http://parsing-and-i.blogspot.com/2009/08/mysql-delphi-express.html</a>
</td>
<td>MySQL и Delphi. Express-метод</td>
</tr>
<tr>
<td>
<a href="http://parsing-and-i.blogspot.com/2009/08/blog-post.html">
http://parsing-and-i.blogspot.com/2009/08/blog-post.html</a>
</td>
<td>Пост о том, что лучше сто раз проверить</td>
</tr>
</table>
</body>
</html>';
// создаем новый dom-объект
$dom = new domDocument;
// загружаем html в объект
$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;
// элемент по тегу
$tables = $dom->getElementsByTagName('table');
// получаем все строки таблицы
$rows = $tables->item(0)->getElementsByTagName('tr');
// цикл по строкам
foreach ($rows as $row)
{ // все ячейки по тегу
  $cols = $row->getElementsByTagName('td');
  // выводим значения
  echo $cols->item(0)->nodeValue.'<br>';
  echo $cols->item(1)->nodeValue.'<br>';
  echo '<hr>';
}
?>

В результате после запуска скрипта получаем такую картину: