Наверное любой программист слэш администратор сайта сталкивается с проблемой импорта данных с чужих сайтов. Задача эта очень тривиальна, и не требует каких-то особых знаний… вопрос только в обертке. Чтобы дополнить коллекцию статей по MODx пишу эту статью, быть может кому и пригодится.
Внимание! Никакой практической ценности данная запись не несет, только теоретическую нагрузку а-ля «Простой пример работы с back-end'ом MODx».
А задача была: таблицу со страницы example.com распарсить, переоформить и себе на сайт засунуть.
Собственно пользоваться мы будем cURL'ом, поскольку для этой цели оптимальнее инструмента не найти. Перво-наперво мы создадим два шаблона parserTplOuter и parserTplInner — соответственно обертка и её «внутренности». Лично я делал таблицу, поэтому в примере будем на это ориентироваться, но никто не запрещает сделать дивы с заданными стилями.
parserTplOuter
Обертка вынесена отдельно специально, чтобы можно было прописать внешний вид, расположение элементов или еще какие-то верстальские штучки не залазя в код. Придерживаемся модели MVC свято!
parserTplInner
Тут хочется пояснить почему я сделал числовые идентификаторы: во-первых, при разработке ассоциативные массивы просто не потребовались :) а во-вторых, хоть и существует шанс запутаться, но зато получается некая стандартизация, когда очень просто добавить еще один элемент в «ряд».
Ну что ж, получили банки, давайте же их наполним соком и создадим сниппет, который назовем parser:
Собственно это все что и требовалось, теперь вставляем в нужном месте на сайте такое:
и видеть сформированную аккуратную табличку.
Стопроцентно ЭТОТ скрипт никому не понадобится, но при наличии головы и серого вещества в ней очень легко адаптировать данный сниппет под свои нужды. Сменить шаблон или механизм обработки вполне просто, вместо обработки таблицы прописать вырезание дива — все равно любой парсинг подоразумевает, что сайт-цель имеет какую-либо статичную структуру. И уже ориентируясь по ней мы получаем данные для обработки, а как их отобразить для решения поставленной задачи уже совсем другая головная боль.
Внимание! Никакой практической ценности данная запись не несет, только теоретическую нагрузку а-ля «Простой пример работы с back-end'ом MODx».
А задача была: таблицу со страницы example.com распарсить, переоформить и себе на сайт засунуть.
Пять копеек
Собственно пользоваться мы будем cURL'ом, поскольку для этой цели оптимальнее инструмента не найти. Перво-наперво мы создадим два шаблона parserTplOuter и parserTplInner — соответственно обертка и её «внутренности». Лично я делал таблицу, поэтому в примере будем на это ориентироваться, но никто не запрещает сделать дивы с заданными стилями.
parserTplOuter
<table>
[+content+]
</table>
Обертка вынесена отдельно специально, чтобы можно было прописать внешний вид, расположение элементов или еще какие-то верстальские штучки не залазя в код. Придерживаемся модели MVC свято!
parserTplInner
<tr>
<td>[+0+]</td><td>[+1+]</td><td>[+2+]</td><td>[+3+]</td>
</tr>
Тут хочется пояснить почему я сделал числовые идентификаторы: во-первых, при разработке ассоциативные массивы просто не потребовались :) а во-вторых, хоть и существует шанс запутаться, но зато получается некая стандартизация, когда очень просто добавить еще один элемент в «ряд».
Ну что ж, получили банки, давайте же их наполним соком и создадим сниппет, который назовем parser:
<?php
if (empty($url)) return false; //если сниппету не дать адреса - завершить исполнение
// тут надо сделать еще кучу проверок на валидность урла, но мы то знаем что зла не напишем сюда
// и балбесам не дадим доступа ;)
$tplInner = (empty($tplInner)) ? 'parserTplInner' : $tplInner; // Зададим умолчательные
$tplOuter = (empty($tplOuter)) ? 'parserTplOuter' : $tplOuter; // чанки для сниппета
$c = (empty($count) || (!is_numeric($count)))? 6 : $count; // Сделаем некое ограничение по кол-ву записей
$c = ($c>100) ? 100 : $c; // максимальное кол-во
$c = ($c<1) ? 1 : $c; // минимальное кол-во
// инициализация сеанса курла
$ch = curl_init();
// установка URL и других необходимых параметров
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// загрузка страницы и выдача её в переменную
$html = curl_exec($ch);
// завершение сеанса и освобождение ресурсов
curl_close($ch);
if (mb_strlen($html) < 100) {return '';} //если ответ слишком короткий для обработки выходим.
//тут надо быть осторожным, поскольку вернутся может самый разнообразный код, но стандартные обрамления HTML в сумме дают примерно 100 символов..
$pattern = "/<table(?:[^>]+)>([\s\S]+)<\/table>/i"; //эта часть вырежет нам все таблицы с сайта.
// теоретически этот шаблон можно запихнуть в чанк и там его менять, но как показывает практика все равно парсинг будет более-менее уникальный для каждого случая, и проще на основе кода написать свой, чем подгонять параметры так, чтобы получился корректный результ...
preg_match($pattern, $html, $matches);
unset($matches[0]); // кто не помнит - в 0 элемент записывается найденая строка целиком и она нам не нужна
$array = explode('</tr>', $matches[1]); //тут я пошел очень хитрым способом и преобразовал все ряды в элементы массива
$separator = '|==|'; $table = array(); // подготовился и...
foreach ($array as &$value) {
//(быдлокод в действии)
$value = str_replace('</td><td', '</td>'.$separator.'<td', $value); // ... сделал финт ушами :)
$value = strip_tags($value); //регулярками убирать тэги таблицы было лениво, проще разделить ячейки служебным набором символов и..
$table[] = explode($separator, $value); //... разбить оставшееся от strip_tags по этому разделителю
}
$i = 0; //здесь стоит отметить, что 0й элемент это заголовки таблицы. если они не нужны, то следует поставить 1 и unset($table[0]); прописать
$rows = '';
foreach ($table as $row) {
//ну теперь пробегаем по каждому ряду
if ($i++ > $c) break; //сверяемся со счетчиком записей
$rows .= $modx->parseChunk($tplRow, $row, '[+', '+]'); //записываем ряд
}
echo $modx->parseChunk($tplTable, array('content'=>$rows), '[+', '+]'); // вставляем ряд и выводим результат
?>
Собственно это все что и требовалось, теперь вставляем в нужном месте на сайте такое:
[[parser?tplInner=`parserTplInner` &tplOuter=`parserTplOuter` &url=`http://example.com` &count=`10`]]
и видеть сформированную аккуратную табличку.
Стопроцентно ЭТОТ скрипт никому не понадобится, но при наличии головы и серого вещества в ней очень легко адаптировать данный сниппет под свои нужды. Сменить шаблон или механизм обработки вполне просто, вместо обработки таблицы прописать вырезание дива — все равно любой парсинг подоразумевает, что сайт-цель имеет какую-либо статичную структуру. И уже ориентируясь по ней мы получаем данные для обработки, а как их отобразить для решения поставленной задачи уже совсем другая головная боль.