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) и разобрать передаваемый массив уже сложностей не составит.

Добавить комментарий