Копируем сайт
АрхивСетевое окружение (архив)Об автоматизации процесса переноса информации на примере одного сайта...
Самой первым вопросом, который нужно решить, приступая к копированию сайта — это выбрать подходящий сайт. Легкость публикации в Сети привела к тому, что найти достойный поставленной задачи сайт не так-то просто. Дело не только в том, что для отыскания среди лавины информации жемчужины сокровенного знания нужен изрядный труд. Многие вполне приличные сайты стали настолько динамичными, завязанными на интерактивность, общение, что копировать их нет никакого смысла. Отпадает также масса чисто развлекательных, ориентированных только на внешние изыски сайтов — их достаточно увидеть один раз.
Но вот мне попался на глаза сайт Softerra.ru и, кажется, там есть статьи, стоящие внимательного прочтения, а также рекомендации коллегам-программистам. Некоторые рубрики, например, Linuxоид, Маковое поле — вполне достойны заполнить дефицит учебной литературы в столь динамичной области, как информатика и программирование. Так что на первый вопрос ответ найден, и мы пытаемся ответить на следующий, не менее важный вопрос — а можно ли копировать этот сайт?
Иногда сайты, разрешённые к копированию, создают все условия для их клонирования — например, www.citforum.ru выкладывает на ftp-архив упакованный файл ежедневных и еженедельных обновлений, а также полную заархивированную копию всего сайта. На видном месте лежит подробная инструкция, как настроить и запустить зеркало этого уникального образовательного сайта. ЦитФорум стал самым первым зеркалом, которое я когда-то давно сделал, за которым внимательно слежу уже много лет.
К счастью, объект нашего внимания — Softerra.ru — относится к копированию довольно либерально. На сайте прямо указаны условия, на которых можно копировать материалы сайта. Так как они непосредственно относятся к постановке задачи, приведу 5 пунктов правил, касающихся копирования статей:
- При использовании статьи необходимо сохранять оригинальное название статьи, указывать имя, фамилию и e-mail автора, а также предварять текст самой статьи сообщением: «Первоначально опубликовано на сайте"Софтерра", www.softerra.ru»…
- Использовать статьи разрешается не ранее, чем через пять рабочих дней после их появления на нашем сайте. Дату публикации любой статьи вы увидите рядом с ее заголовком.
- Если в конце статьи приведены ссылки на близкие по теме материалы на нашем сайте, то вы должны сохранять их при размещении статьи на вашем сайте.
- В конце статьи вы обязательно должны указать «Copyright © "Софтерра", www.softerra.ru, inform@softerra.ru».
- И, наконец, самое важное: в конце статьи вы обязательно должны разместить блок из как минимум трех анонсов последних статей на сайте «Софтерры». Для этого поместите нижеприведенный код после завершения текста статьи. Считайте это скромной оплатой труда наших авторов.
Сделаем в этом месте небольшое лирическое отступление. Конечно, любое требование владельца авторских прав является законным. Если бы автор web-страницы вдруг потребовал: «для того, чтобы читать моё сочинение дальше, немедленно переведите на мой счёт Q рублей» (имеется в виду Q-большое) — это его условие было бы вполне законно. Но такое требование было бы неразумно, так как любой здравомыслящий И (логическое И) честный человек вряд ли бы дочитал его страницу до конца. Правила же, составленные редакцией «Софтерры», вполне разумны, мы может только пожелать им успеха в нелёгком бизнесе web-издания.
Замечу также, что по мнению многих уважаемых хакеров, в частности, Ричарда М. Столмена, сообщества разработчиков Debian — отсутствие явного разрешения на копирование программы или документа равносильно запрету на копирование. Копировать любое авторское произведение можно, только если автор или владелец прав на него прямо дал такое разрешение, и только на указанных автором условиях.
Теперь мы приступим к изучению сайта Softerra.ru, чтобы узнать, а можно ли как-то запрограммировать процесс копирования. Конечно, хорошо настроенный кэш позволит, вволю пощёлкав кнопками, получить более-менее представительное подмножество сайта где-то в глубине каталогов вашего диска. Эти разрозненные страницы вряд ли можно назвать копией сайта.
Поэтому выберем отдельные рубрики, представляющие наибольший интерес, — для примера, каталог /freeos, и изучим его устройство. Оказывается, на страницах /freeos/pageN.html хранится список опубликованных статей. Ручное копирование этих страниц нам совершенно не интересно, так что пора подумать о хорошем инстументе для работы.
Самым удобным инструментом для общения с компьютером являются, бесспорно, классические юниксовые средства. Вглядитесь, что за мощь скрыта в командном процессоре bash, в языках awk, perl, в изящных текстовых и файловых утилитах, в потоковом редакторе sed. Как хорошо они взаимодействуют друг с другом, как гармоничен их ансамбль. Руки так и просят потрогать эти прекрасные инструменты, ощутить их силу и послушность. Если у вас такое же желание, можете провести небольшую разминку, к примеру, вот с этими микрохаками: gomelug.agava.ru/articles/micro-hacks.html.
Вот уж, воистину, такими инструментами можно и храм построить, и бороду сбрить (хакер, устар. — тот, кто топором бреется:)).
Таким образом, уяснив, что список интересующих нас статей находится на указанных выше страницах, мы первым делом получаем эти страницы:
... $ site=http://www.softerra.ru
... $ win2koi=ЧЮАЖДЕТЦУХИЙКЛМНОЪПЯРСФБЭШГЬЩЫВЗчюаждетцухийклмноъпярсфбэшгьщывз
... $ for i in $(seq 1 10);do wget $site/freeos/page$i.html -O -|
> tr $win2koi ю-ъЮ-Ъ>page$i.html;done
Здесь я по ходу сделал перекодировку из кодовой страницы cp1251 в принятую в моей системе КОИ-8. Если у вас принята другая кодировка, эта операции не нужна и строка-программа упрощается. Строку для перекодировки можно всегда получить, воспользовавшись, например, следующим:
... $ perl -e 'use locale;print grep/\w/,map{chr()}128..255'
А затем перегнать её в cp1251 любым из имеющихся перекодировщиков. Можете смело пользоваться приведенной выше строкой, я её все равно руками не набирал (стучу по клавишам клювом :)).
По прибытии страниц с оглавлениями придётся внимательно их просмотреть на предмет координат собственно статей. Здесь нас ждёт приятная находка — оказывается, программисты Софтерры уже предусмотрели версии статей, предназначенные для печати и очищенные от массы служебной и рекламной информации. Ура, самая неприятная работа — выковыривание из html-кода полезной информации, уже сделана. Чистые и компактные страницы хранятся в файлах /freeos/NNNNN/print.html, где NNNNN, видимо, порядковый номер статьи.
Попробуем использовать найденную регулярность и выбрать из оглавлений точные адреса статей. Воспользуемся возможностью языка perl для отладки и визуализации регулярных выражений.
... $ perl -wne 'print "$1\n" if m#href=/(\w+/\d+)/page1.html#' page*.html
Убедившись, что мы находим именно то, что нам надо, присвоим найденный список каталогов переменной list. При желании этот список можно записать в файл и подредактировать, но мы постараемся решить задачу самыми минимальными средствами. Хотя я снова приведу эту довольно длинную строку-программу, вы, конечно, знаете, что при работе в шелле она берётся из history и чуть-чуть редактируется.
list=$(perl -wne 'print "$1\n" if m#href=/(\w+/\d+)/page1.html#' page*.html)
Нам желательно выбрать из адреса отдельно имена каталогов, поэтому сделаем ещё одно отладочное действие, а именно:
... $ for i in $(echo "$list");do n=${i##*/};d=${i%$n};echo $d $n;done
Эти магические знаки и скобки позволяют выбирать из слова его части средствами самого bash'а, не привлекая без нужды посторонние средства. Отладив выражение, дадим ему настоящее задание:
... $ for i in $(echo "$list");do n=${i##*/};wget $site/$i/print.html -O -|
> tr $win2koi ю-ъЮ-Ъ>$n.html;done
Снова попутно выполнено необязательное перекодирование. Имеющиеся на некоторых страницах иллюстрации извлекаются с сайта Софтерры так же просто:
... $ list=$(perl -wne 'print "$1," if m#src="/((?:\w+/)+\w+\.(?:gif|jpg))#'\
> [0-9]*.html)
... $ eval echo $site/{$list}|wget -i -
Мы успешно получили все заинтересовавшие нас статьи, но ещё не выполнили перечисленных правовладельцами условий копирования. Если я хочу поместить эти страницы у себя на сайте, а задумано было именно так, то наша процедура копирования ещё не закончена. Как вы помните, Софтерра требует вставить несколько дополнительных строк и ссылок. Займёмся теперь этим, заодно опробуем в действии ещё пару утилит и слегка поправим полученные странички.
Ничто нам не запрещает удалить очень подробную информацию из мета-тэгов — она предназначена для поисковиков, а обычной читающей публике ничего нового не сообщает. Снова призовём perl:
... $ perl -i.bak -wpe 's#<meta name="[^>]+>##' *.html
Ключ -i.bak нужен только для подстраховки, чтобы убедиться, что регулярное выражение составлено правильно и получено то, что хотелось. После проверки оригинальные файлы можно смело удалить.
... $ rm *.bak
... $ perl -i -wpe 's#src="/include/script#src="include/script#' *.html
... $ perl -i -wpe 's#src="/pubimages#src="pubimages#g' *.html
... $ mkdir pubimages; mv *.gif *.jpg pubimages
Этими простыми операциями мы отвязали наши ссылки от корневого каталога и переместили картинки в отдельный каталог. Теперь приступим к вставке требуемых Софтеррой строк и ссылок. Давайте приготовим эти строки заранее, чтобы воспользоваться трудно передаваемым в статике способом работы с мышью drag-&-drop.
... $ echo '<p>(C) Copyright "Софтерра", > <a href="http://www.softerra.ru">www.softerra.ru</a>,
> <a href="mailto:inform@softerra.ru">inform@softerra.ru</a>.'
... $ echo '<p><script src="http://www.softerra.ru/> softerra-articles-js.html?articlecount=5">
</script>'
Здесь мне пришлось разбить эти строки на несколько строк для компактности, на самом деле это 2 длинных строки. Чуть позже я на них сошлюсь как доп.строка1 и доп.строка2. Вставляются они в нужное место с помощью мыши — отмечаем блок, удерживая левую кнопку, а затем вставляем в нужное место, подведя курсор и нажав правую кнопку мыши. Вот какое длинное описание элементарной процедуры получилось. Будем, однако, радоваться, что обошлось без нескольких страниц скриншотов.
Место, куда мы вставим эти строки, выберем в самом конце файла, там, где находится контекст </div><br></body>
... $ perl -i -wpe 's#</div><br></body>#> доп.строка1> доп.строка2> </div></body>#' *.html
В завершение выполним ещё одну операцию — названия файлов у нас какие-то порядковые номера, что неудобно. Благо, в каждой статье есть заголовок, давайте так и назовем каждый из файлов.
... $ for i in [0-9]*.html;do fn=$(grep '<h1>' $i| > sed 's#^.*<h1>\(.*\)</h1>.*$#\1#;> s/ /_/g;> s/\&.*;//g;> s#[!?/]#~#g;> s/\.*$//');
mv $i $fn.html;done
Здесь нам пришлось повозиться с именами файлов — сначала извлечь заголовок, затем заменить пробелы на знак подчёркивания, затем убрать сомнительные знаки и лишние точки. Теперь в основном наша задача выполнена. Получение и размещение отдельных файлов — script.js, print.css автоматизации не подлежит и выполняется вручную.