Последнее время мне очень часто приходится парсить страницы разных сайтов. Когда я начинал изучать эту тему, то заметил, что есть 2 подхода к анализу контента страницы: анализ регулярными выражениями и с помощью phpQuery или simpleHtmlDOM. Будучи не сторонником использования чужих библиотек я выбрал 1ый путь.
Разбираемся в регулярках
Начнем с описания синтаксиса регулярных выражений.
Разберем простейший шаблон:
<(h1|h2|h3)><a href=”(.*?)”>(.*?)</a></(h1|h2|h3)>
( ) является подшаблоном знак | означает или, то есть подшаблон (h1|h2|h3) означает вхождение или h1, или h2, или h3. Точка в подшаблоне (.*?) обозначает любой символ. * - неограниченное количество совпадений. А ? оптимизирует и минимизирует, но об этом позже. Кроме того в preg_match этот подшаблон отвечает за искомый фрагмент текста.
В регулярных выражениях существует еще и другой тип шаблонов: #шаблон#
#a|z# означает вхождение a или z.
Совпадает в строках:
Abraham J. Simpson
go to the zoo
и не совпадает в строке
Home sweet home (нет ни a, ни z)
#ˆa# - символ находится в начале строки
#т$# - символ находится в конце строки
Можно также указать количество совпадений.
{ } - эти знаки в шаблоне обозначают сколько раз должно быть совпадение
? тоже самое, что и {0,1} - ноль или один раз
* тоже самое, что и {0, } - ноль или более раз
+ тоже самое, что и {1, } - один или более раз
первая цифра-минимальное количество совпадений, вторая — максимальное(если её нет, то бесконечное количество).
Кроме этого, классы символов можно обозначать так:
[[:alnum:]] - все алфавитно-цифровые символы [a-zA-Z0-9]
[[:alpha:]] - все алфавитные символы [a-zA-Z]
[[:blank:]] - символ табуляции и пробел [t ]
[[:cntrl:]] - все управляющие символы
[[:digit:]] - все десятичные цифры [0-9]
[[:graph:]] - все печатные символы, за исключением пробела
[[:lower:]] - все строчные буквы [a-z]
[[:upper:]] - все прописные буквы [A-Z]
[[:print:]] - все печатные символы
[[:punct:]] - все знаки препинания [.,;:-.,;:-]
[[:space:]] - все пустые символы
[[:xdigit:]] - все шестнадцатиричные цифры
точка. — любой символ(. - только точка).
Модификаторы:
ставятся после шаблона, например #шаблон#i
i - игнорировать регистр
s - метасимвол '.' соответствует и символу n (перевод каретки), то есть классу [-xFF-xFF]
U - минимизировать числитель, то есть искать как можно меньше совпадений, похоже на действие ?.
m - претензии 'ˆ' и '$' учитывают [n]
D - претензия '$' не учитывает [n]
A - привязать шаблон к началу текста
x - разрешить комментарии: пробел и #
X - воспринимать неверную подстановку как ошибку.
S - предварительная оптимизация шаблона
e - используется в функции 'preg_replace' для ее активации
Регулярные выражения в действии
И так, немного разобравшись в теории, преступим к практике.
Решим легонькую задачку - найти все ссылки на странице:
$content=file_get_contents("http://7ion.ru");//берем страницу $LinksArray=NULL;//тут будут ссылки preg_match_all("/<a[[:print:]]href=["|'](.*?)["|'].*?>(.*?)<.{0,1}a.{0,1}>/i",$content,$LinksArray,PREG_PATTERN_ORDER);//применяем регулярку var_dump($LinksArray);//выводим ссылки |
Основой кода является выражение "/<a[[:print:]]href=["|'](.*?)["|'].*?>(.*?)<.{0,1}a.{0,1}>/i"
давайте разберем его:
первым делом ищем тег ссылки: <a[[:print:]]href=["|'](.*?)["|'].*?> нам нужен только url, но к сожалению обойтись выражением типа <a href=”(.*?)”> не удастся. Во-первых в теге могут присутствовать разного рода включения(типа style или onclick), от них избавляемся шаблоном [[:print:]], а во-вторых неизвестно какие кавычки будут ограничивать адрес(используем шаблон ["|']-или " или ').
Текст ссылки берем шаблоном (.*?), а на закрывающий тег натравливаем <.{0,1}a.{0,1}> так как не знаем куда вебмастер поставит символ /. Естественно необходимо применить модификатор i чтоб не думать о регистре.
Думаю теперь вам под силу отпарисить любую страницу, если возникнут трудности, пишите, помогу.