Отправляет email-рассылки с помощью сервиса Sendsay

KirovLUG: пользователи Linux в Вятке

RSS-ленты. Скрипт на Python для зеркалирования rss-лент.

RSS-ленты. Скрипт на Python для зеркалирования rss-лент.

В Инете все большую популярность набирает формат RSS (Really Simple
Syndication) (http://naklon.debilarius.ru/texts/sleep/rss.htm - здесь
можно почтитать о том как добавить поддержку rss на сайт). Этот формат
обычно используется для передачи новостей с новостных сайтов и вещания с
всевозможных ЖЖ (live journal). Чем он удобен? А тем что на самих сайтах
информация может теряться в оформлении или же посещение самих сайтов
чревато большим потреблением трафика, а RSS, основанный на XML, тянет
обычно только текстовую информацию самих новостей, да служебную
информацию, такую как автора, дату, ссылку на материал в Инете.

Информацию в формате RSS можно просматривать как с помощью специальных
RSS-читалок, так и используя средства встроенные в популярный
Интернет-инструментарий: Firefox, Thunderbird, Opera.

Итак, в очередной раз обходя интересные мне сайты, я пытался выловить из
них те, которые предоставляют rss информацию. В Opera это делать очень
удобно - если сайт поддерживает такой сервис, то в строке ввода адреса с
правой стороны появляется прямоугольник с буквами "RSS". Если нажать по
этому прямоугольнику, то браузер предложить добавить наблюдение за этим
каналом. Но работать с RSS в Opera мне не очень понравилось, поэтому
необходимые мне новостные каналы я добавляю в Thunderbird,
предварительно создав там специальную учетную запись "RSS News & Blogs"
(т.к. у меня соединение с Инетом не постоянное, то я убрал галочку у
"Проверять наличие новых статей каждые X минут", и поставил галку у "По
умолчанию показывать краткое описание статьи вместо загрузки веб-страницы").

Вот ссылки которые я получил:

http://www.linux.org.ru/rss.jsp
http://www.linuxcenter.ru/trans/news.rss
http://www.osrc.info/files/backend/news.xml
http://www.nixp.ru/news/headlines.xml
http://www.opennet.ru/opennews/opennews_6.rss
http://www.ixbt.com/export/news.rdf
http://www.uinc.ru/news/show.php?rss=main
http://www.netpeoples.ru/files/backend/news.xml
http://www.livejournal.com/users/vadim_kataev/data/rss

Несколько слов можно сказать о том, как выглядит ссылка на rss внутри
кода http-страницы. Это специально оформленный тег "link" внутри секции
"head":

<link rel="alternate" type="application/rss+xml" title="RSS"
href="http://www.livejournal.com/users/vadim_kataev/data/rss" />

<LINK REL="alternate" TITLE="L.O.R RSS" HREF="//linux.org.ru/rss.jsp"
TYPE="application/rss+xml">

Но на этом я не хотел останавливаться. Я подумал: т.к. можно заставить
машину автоматически забирать почту в момент подсоединения к Инету и
помещать ее в почтовые ящики, из которых потом пользователи смогут
забирать почту когда машина будет в offline, то можно также забирать
rss-информацию с сайтов и выкладывать ее на локальном веб-сервере.

Первым делом, попробуем получить rss-файл с сервера:

$ wget -nd http://www.linux.org.ru/rss.jsp

Все легко и просто скачивается. Поэтому для получения информации со всех
сайтов можжно будет написать простой скрипт:

#!/bin/sh

wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.linux.org.ru/rss.jsp
wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.linuxcenter.ru/trans/news.rss
wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.osrc.info/files/backend/news.xml
wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.nixp.ru/news/headlines.xml
wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.opennet.ru/opennews/opennews_6.rss
wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.ixbt.com/export/news.rdf
wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.uinc.ru/news/show.php?rss=main
wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.netpeoples.ru/files/backend/news.xml
wget -nd -t 1 -P /var/www/wacko/library/rss/ \
http://www.livejournal.com/users/vadim_kataev/data/rss
Казалось бы - все, но в результирующем каталоге у нас получится винигрет
из-за разношерстного названия файлов:

rss.jsp
news.rss
news.xml
headlines.xml
opennews_6.rss
news.rdf
show.php?rss=main
news.xml.1
rss

Также видно, что rss-файлы с osrc.info и netpeoples.ru называются
одинаково. Ориентироваться в таких файлах можно будет только методом
"тыка". Следовательно, неплохо было бы переименовывать получаемые файлы.

Поэтому создадим некоторый файл rss.list, который бы содержал информацию
о том, что нужно скачать и во что переименовать результат. Файл будет
следующего вида:

-*- lor.rss -*-
http://www.linux.org.ru/rss.jsp
-*- linuxcener.rss -*-
http://www.linuxcenter.ru/trans/news.rss
-*- osrc.rss -*-
http://www.osrc.info/files/backend/news.xml
-*- nixp.rss -*-
http://www.nixp.ru/news/headlines.xml
-*- opennet.rss -*-
http://www.opennet.ru/opennews/opennews_6.rss
-*- ixbt.rss -*-
http://www.ixbt.com/export/news.rdf
-*- uinc.rss -*-
http://www.uinc.ru/news/show.php?rss=main
-*- netpeoples.rss -*-
http://www.netpeoples.ru/files/backend/news.xml
-*- vadim_kataev.rss -*-
http://www.livejournal.com/users/vadim_kataev/data/rss
О, теперь порядок. Осталось только написать скрипт, который бы
обрабатывал данные из этого файла:

begin rss_get.py #!/usr/bin/env python
# -*- coding: KOI8-R -*-

# Скрипт для загрузки файлов из Интернет (применяется wget).
# Используется с двумя аргументами: file и dir.
# file - файл со списком получаемых данных, например:
# -*- lor.rss -*-
# http://www.linux.org.ru/rss.jsp
# http://www.linuxcenter.ru/trans/news.rss
# -*- osrc.rss -*-
# http://www.osrc.info/files/backend/news.xml
# Строка с -*- перед url - новое имя файла после загрузки, если она
# отсутствует, то файл не переименовывается
# dir - какталог куда помещать результаты

import sys, os, string
from glob import glob

# Переменные, в которых хранятся параметры, полученные из командой
# строки
filesrc = ""
putpath = ""

# Если было передано меньше или больше параметров, то завершить скрипт
if len(sys.argv) != 3:
print "Usage: "+sys.argv[0]+" <file> <dir>"
sys.exit(1)

filesrc = sys.argv[1]
putpath = sys.argv[2]+"/"
# Если файла со списком не существует, то завершить скрипт
if os.path.isfile(filesrc) == 0:
print "File not exist"
sys.exit(1)
# Если каталога назначения не существует, то завершить скрипт
if os.path.isdir(putpath) == 0:
print "Dir not exist"
sys.exit(1)

# Открываем файл со списком
fd = open(filesrc, 'r')

# Имя файла, в который переименовываем
newname = ""
# url - данные для получения
fileget = ""

# Цикл чтения строк из файла
while 1:
# Читаем строку из файла
s = string.rstrip(fd.readline())
# Если достигли конца файла, то прервать цикл
if not s:
if newname != "":
print "fileget?"
else:
print "done"
break
# Если полученная строка содержит "-*-", то это имя нового файла
if s.find("-*-") != -1:
newname = string.strip(s.replace("-*-", ''))
fileget = ""
# Если начинается с "http://", то это url
elif s.startswith("http://") == 1:
# Выделяем из url старое название файла
oldname = s[s.rfind('/')+1:]
# Осуществляем закачку
r = os.system("wget -nd -t 1 -P "+putpath+" "+s)
# Если закачка прошла без ошибок
if r == 0:
# Если не был указан файл для переименования
if newname == "":
# Определяем старые версии этого файла
dupfiles = glob(putpath+oldname+"*")
# Если старые версии были
if len(dupfiles) != 0:
# Удаляем все версии кроме последней
map(os.unlink, dupfiles[0:-1])
# Переименовываем последнюю версию
os.rename(dupfiles[-1], putpath+oldname)
# Был указан файл для переименования
else:
# Переименовываем файл
os.rename(putpath+oldname, putpath+newname)
newname = ""
fileget = ""
# Путсые строки пропускаем
elif s == "":
pass
# На строки другого формата ругаемся
else:
print "string not defined"

# Закрываем файл
fd.close()
end rss_get.py Для изучающих Python небольшие справки по используемым функциям:

sys.argv - список, содержащий параметры, передаваемые скрипту из
командной строки, в sys.argv[0] содержится имя самого скрипта.
sys.exit(1) - прервать выполнение скрипта и выйти с ненулевым
результатом. Обычно если результат не нулевой, то это свидетельствует о
некорректном завершении работы программы.
os.path.isfile(filesrc) и os.path.isdir(putpath) - определяют является
(существуют) ли передаваемый им параметр файлом и каталогом
соответственно. Если ответ положительный возвращают 1, иначе 0.
open(filesrc, 'r') - открывает файл на чтение, и возвращает файловый
дескриптор, необходимый для выполнения других операций с файлом.
fd.readline() - возвращает одну считываемую из файла строку,
завершающуюся символом перехода на новую строку.
fd.close() - закрывает используемый файл.
string.rstrip(s) - возвращает копию строки с удаленными идущими в конце
строки символами пропуска (пробел, табуляция, переход на новую строку и
т.д.).
string.strip(s) - возвращает копию строки с удаленными идущими в начале
и конце строки символами пропуска.
s.find("-*-") - возвращает наименьший индекс вхождения подстроки в
исходную строку.
s.rfind('/') - возвращает наибольший индекс вхождения подстроки в
исходную строку.
s.replace("-*-", '') - возвращает копию строки, в которой все вхождения
подстроки "-*-" заменены на ''.
s.startswith("http://") - Возвращает 1, если строка начинается с "http://"
os.system("wget -nd -t 1 -P "+putpath+" "+s) - выполняет в командном
интерпретаторе команду, указанную как аргумент. В качестве результата
возвращает код завершения выполнения команды.
glob(putpath+oldname+"*") - возвращает список имен путей,
удовлетворяющих заданому шаблону.
map(os.unlink, dupfiles[0:-1]) - выполняет функцию os.unlink с каждым
элементом списка dupfiles[0:-1] в качестве параметра.
os.unlink(s) - удаляет файл
os.rename(dupfiles[-1], putpath+oldname) - переименовывает файл
переданный в качестве первого параметра, новое имя - второй параметр.
pass - команда ничего не делания.

Теперь, если после выход в Интернет выполнить данный скрипт:

$ ./rss_get.py /home/koal/rss.list /var/www/wacko/library/rss/

В каталоге /var/www/wacko/library/ получится набор rss-файлов. Остается
для автоматической закачки добавить эту строку запуска в конец файла
/etc/ppp/if-up.local.

Сейчас для пользователей локального сайта они будут теперь доступны по
следующим адресам:

http://wiki/library/rss/ixbt.rss
http://wiki/library/rss/linuxcener.rss
http://wiki/library/rss/lor.rss
http://wiki/library/rss/nixp.rss
http://wiki/library/rss/opennet.rss
http://wiki/library/rss/osrc.rss
http://wiki/library/rss/uinc.rss
http://wiki/library/rss/netpeoples.rss
http://wiki/library/rss/vadim_kataev.rss

Пользователям имеющим доступ к моему серверу (дозванивающимся к dial-in
серверу), остается только вбить эти ссылки в свои rss-читалки, чтобы
получать новости не выходя в Инет.

Ответить   Thu, 27 Jan 2005 11:34:33 +0300 (#305453)

 

Ответы:

так как запуск этого скрипта происходит от пользователя root, то
создаваемые файлы получатся только для чтения для этого пользователя,
поэтому добавим в скрипт функции смены прав после функций переименования:

os.rename(dupfiles[-1], putpath+oldname)
os.chmod(putpath+oldname, 420)
else:
os.rename(putpath+oldname, putpath+newname)
os.chmod(putpath+newname, 420)

os.chmod(putpath+oldname, 420) - меняет права доступа к файлу, права
задаются в виде целого числа. 420 соответствует правам 655.

Ответить   Fri, 28 Jan 2005 09:00:57 +0300 (#306092)