PHP: учимся работать с regexp
Зашла тут на днях речь об изучении регулярных выражений. Моё мнение, что лучшее учёба, это практика, по этому была поставлена простенькая задача: получить страницу http://www.specialist.ru/section/web-programming, разбирать при помощи регулярных выражений (имя курса, ссылку на него и кол-во часов) и вывести список курсов в таблицу.
Сейчас мы и попытаемся решить эту задачу
Для начала нам необходимо определится с последовательностью действий:
1. получаем страницу
1.1 необходимо изучить исходник страницы, на тему содержащихся данных, что бы понять — каким образом её разобрать при помощи регулярных выражений
2. получаем данные со страницы, при помощи регулярных выражений
3. удобнее собирать данные в массив, этим и займёмся
4. распарсить массив и вывести данные в таблицу
При первом рассмотрении страниц сайта, становится понятно что страницы со списком курсов однотипны (ну что в принципе не удивительно, т.к. всё выводится при помощи скриптов). Соответственно наш парсер будет работать с любой страницей курсов, тогда возможно начать с того, что бы дать пользователю возможности самому выбирать — какую страницу парсить. Соответственно здесь всё достаточно просто, ибо обычный html:
<form method="post"> <input name="link" type="text" value="http://www.specialist.ru/section/web-programming" /> <input type="submit" /> </form>
Значит первым делом мы передаём нашему скрипту ссылку на курс, соответственно первым делом мы проверяем отправленную нам ссылку (не в коем случае не забываем о том что все отправленные пользователем данные мы всегда должны проверять, дабы не получить неприятных осложнений) и если всё в порядке — запускам функцию, которая будет выполнять всю работу, в противном случае выводим сообщение об ошибке.
if (isset($_POST['link'])) { $check = stripos($_POST['link'], "http://www.specialist.ru"); if ($check !== false) { $content = file_get_contents($_POST['link']); regexp($content); } else { echo "Введёная вами ссылка ведёт <b>не</b> на сайт www.specialist.ru. Скрипт остановлен."; } }
мне нравится isset(), но можно в принципе заменить и на конструкцию
if ($_SERVER["REQUEST_METHOD"] == "post");
кому что больше нравится.
Что делает вышеприведённый код? При помощи функции stripos() мы проверяем содержит ли передаваемая ссылка — http://www.specialist.ru (попытались неким образом это дело отфильтровать, что бы нам не пришлось работать в пустую, если нам подсунут например ссылку на Яндекс), если не содержит — выводим пользователю сообщение — «Введёная вами ссылка ведёт не на сайт www.specialist.ru. Скрипт остановлен.», иначе — при помощи функции file_get_contents() получаем страницу, и её содержимое передаём нашей функции regexp(), которая и будет у нас заниматься обработкой и выводом данных.
Соответственно теперь переходим к нашей функции: мы уже определились что данные у нас будут хранится в массиве, соответственно первым делом нам нужно проинициализировать 3 массива — название курса, кол-во часов, ссылка. Теперь переходим к регулярным выражениям. Сразу оговорюсь — каждое совпадение данных мы будем в цикле отправлять в наши 3 массива, а уже из этих 3 массивов мы потом сделаем один многомерный массив, который и будем разбирать при выводе данных.
function regexp($content) { $name_array = array(); $hours_array = array(); $links_array = array(); #course name and link preg_match_all("/<td class=\"td_course\">\s+(<strong>)?<a href=\"([^\"]+)\">([^<]+)</", $content, $array); foreach ($array[2] as $key => $val) array_push($links_array, strip_tags($val)); foreach ($array[3] as $key => $val) array_push($name_array, strip_tags($val)); #hours preg_match_all("/<td>\d{1,3}<\/td>/", $content, $array2); foreach ($array2[0] as $key => $val) array_push($hours_array, strip_tags($val)); $courses = array("name"=>$name_array,"hours"=>$hours_array,"links"=>$links_array); showtable($courses); }
Ну и теперь осталось лишь вывести всё это. Думаю написать функцию showtable($courses) и разобрать передаваемый массив уже сложностей не составит.