Log in

Bekijk de volledige versie : Скрипт для скачивания подкастов Python + Google Reader



1ac3124
05-10-2008, 11:52
Когда количество прослушиваемых подкастов перевалило за 3 стало достаточно сложно следить за ними всеми. Пользоваться агрегаторами монстрами типа iTunes нет желания, да и проблемы с ними тоже возникают: то в забуду тыкнуть кнопочку обновить/скачать, то времени не хватает дождаться скачивания. В общем проблема автоматической доставки подкаст-контента поближе ко мне видна на лицо. Решение проблемы принялся искать кардинально, но удобное. В итоге на был найден питоновский скрипт для автоматического скачивания подкастов из ленты Google Reader. Дело осталось за малым: запустить всё это на роутере.

Список подкастерских лент храним Google Reader (http://www.google.ru/reader/). Ленты помечены своим тегом, и аккуратно лежат в своей папке. В качестве основы скрипта взята библиотеку pyrfeed (http://code.google.com/p/pyrfeed/), в которой реализован полезный класс GoogleReader.

1. Сначала ставим Python (на время написания статьи текущая версия в репозитории 2.5):

ipkg install python
ipkg install py25-elementtree
ipkg install py25-cheetah
ipkg install py25-cherrypy
2. Распаковываем pyrfeed-0.5.1.rar (http://1ac3124.tzo.org/pyrfeed-0.5.1.rar) в /opt/lib/python2.5

3. Содержимое PodcastDownloadTool.rar (http://1ac3124.tzo.org/PodcastDownloadTool.rar) распаковываем в любое удобное вам место, например /opt/urs/bin/

4. Настраиваем скрипт PodcastDownloadTool.py под себя:
downloadDir – каталог, куда будут скачиваться подкасты
logFile – название лог файла
tag – имя тега/папки в Google Reader, в которой будут просматриваться ленты
login и password – логин и пароль в Google Reader

5. Проверяем работоспособность:

python /opt/usr/bin/PodcastDownloadTool.py
В ответ мы должны получить как минимум "Login OK", если есть непрочитанные ленты подкастов, то начнётся их скачивание.

6. Осталось заставить выполнять роутер запускать скрипт раз в час/день кому как удобно. Создаем в /opt/etc/cron.hourly (или /opt/etc/cron.daily) скрипт (например PodcastDownloadTool.sh) следующего содержания:

#!/bin/sh
python /opt/usr/bin/PodcastDownloadTool.py >> /opt/var/log/PodcastDownloadTool.log 2>&1

На этом собственно всё, осталось указать на маленькие недостатки:

Не поддерживается докачка. В случае сбоя RSS-запись не будет помечена как прочитанная. При следующем запуске скрипта файл будет выкачан заново.
Отсюда следующий момент – при следующем запуске скрипта, ошибочные записи (например, в записи нет ссылки на файл для скачивания) будут повторно обрабатываться. Можно бы их метить специальным тегом и пропускать в дальнейшем. Но меня устраивает последующий ручной просмотр ленты на предмет не прочитанных записей.
Хранение конфигурации – логин и пароль в открытом виде. Логин еще не так страшно, а вот пароль (если у кого-то паранойя, то можно ради этого завести пустого пользователя в GoogleReader)



Мануал написан на основе статьи из блога Yustos (http://yustos.ru/blog/podcast-downloading-with-python-and-google-reader).

kibenimatik
06-10-2008, 19:12
Здорово. Я как раз думал о том как организовать автоматическую загрузку программы телепередач. Спасибо за наводку.

RekoD
05-01-2009, 22:22
Пробовал поднять proxymin на WL500gPV2 (на x86 работает на ура), но получил следующее:


--> -->


DBInvalidArgError Python 2.4.5: /opt/bin/python2.4
Tue Jan 6 00:59:27 2009

A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred.
/opt/share/www/ctrl/proxymin.py
91 # call appropriate page
92 if(action == ACTION_SHOW_MAIN):
93 gui_main.print_main_page(category, letter, group)
94 elif(action == ACTION_DISPLAY_HELP):
95 gui_help.print_help_page()
gui_main = <module 'gui_main' from '/opt/share/www/ctrl/gui_main.py'>, gui_main.print_main_page = <function print_main_page>, category = 'groups', letter = None, group = None
/opt/share/www/ctrl/gui_main.py in print_main_page(category='groups', letter=None, group=None)
30 """display administration main page"""
31 gui_misc.print_html_head()
32 print_title_bar()
33 print '<br><br>'
34 print_tabs(category)
global print_title_bar = <function print_title_bar>
/opt/share/www/ctrl/gui_main.py in print_title_bar()
51 def print_title_bar():
52 # count all user/host/group objects
53 iterator = objectiterator.ObjectIterator(CATEGORY_HOSTS)
54 number_of_hosts = iterator.get_object_count()
55 iterator.set_category(CATEGORY_USERS)
iterator undefined, global objectiterator = <module 'objectiterator' from '/opt/share/www/ctrl/objectiterator.py'>, objectiterator.ObjectIterator = <class objectiterator.ObjectIterator>, global CATEGORY_HOSTS = 'hosts'
/opt/share/www/ctrl/objectiterator.py in __init__(self=<objectiterator.ObjectIterator instance>, category='hosts')
25 """uniform interface to access different object types - simplifies GUI programming"""
26 def __init__(self, category):
27 self.dba = dbaccess.DBAccess()
28 self.set_category(category)
29
self = <objectiterator.ObjectIterator instance>, self.dba undefined, global dbaccess = <module 'dbaccess' from '/opt/share/www/ctrl/dbaccess.py'>, dbaccess.DBAccess = <class dbaccess.DBAccess>
/opt/share/www/ctrl/dbaccess.py in __init__(self=<dbaccess.DBAccess instance>)
39 """persistence framework"""
40 def __init__(self):
41 self.users = shelve.open(userdb)
42 self.hosts = shelve.open(hostdb)
43 self.groups = shelve.open(groupdb)
self = <dbaccess.DBAccess instance>, self.users undefined, global shelve = <module 'shelve' from '/opt/lib/python2.4/shelve.pyc'>, shelve.open = <function open>, global userdb = 'db//users'
/opt/lib/python2.4/shelve.py in open(filename='db//users', flag='c', protocol=None, writeback=False, binary=None)
230
231 See the module's __doc__ string for an overview of the interface.
232 """
233
234 return DbfilenameShelf(filename, flag, protocol, writeback, binary)
global DbfilenameShelf = <class shelve.DbfilenameShelf>, filename = 'db//users', flag = 'c', protocol = None, writeback = False, binary = None
/opt/lib/python2.4/shelve.py in __init__(self=<DbfilenameShelf instance>, filename='db//users', flag='c', protocol=None, writeback=False, binary=None)
213 def __init__(self, filename, flag='c', protocol=None, writeback=False, binary=None):
214 import anydbm
215 Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback, binary)
216
217
global Shelf = <class shelve.Shelf>, Shelf.__init__ = <unbound method Shelf.__init__>, self = <DbfilenameShelf instance>, anydbm = <module 'anydbm' from '/opt/lib/python2.4/anydbm.pyc'>, anydbm.open = <function open>, filename = 'db//users', flag = 'c', protocol = None, writeback = False, binary = None
/opt/lib/python2.4/anydbm.py in open(file='db//users', flag='c', mode=438)
79 # db type cannot be determined
80 raise error, "db type could not be determined"
81 else:
82 mod = __import__(result)
83 return mod.open(file, flag, mode)
mod = <module 'dbhash' from '/opt/lib/python2.4/dbhash.pyc'>, mod.open = <function open>, file = 'db//users', flag = 'c', mode = 438
/opt/lib/python2.4/dbhash.py in open(file='db//users', flag='c', mode=438)
12
13 error = bsddb.error # Exported for anydbm
14
15 def open(file, flag = 'r', mode=0666):
16 return bsddb.hashopen(file, flag, mode)
global bsddb = <module 'bsddb' from '/opt/lib/python2.4/bsddb/__init__.pyc'>, bsddb.hashopen = <function hashopen>, file = 'db//users', flag = 'c', mode = 438
/opt/lib/python2.4/bsddb/__init__.py in hashopen(file='db//users', flag='c', mode=438, pgsize=None, ffactor=None, nelem=None, cachesize=None, lorder=None, hflags=0)
289
290 flags = _checkflag(flag, file)
291 e = _openDBEnv(cachesize)
292 d = db.DB(e)
293 d.set_flags(hflags)
e undefined, global _openDBEnv = <function _openDBEnv>, cachesize = None
/opt/lib/python2.4/bsddb/__init__.py in _openDBEnv(cachesize=None)
345 else:
346 raise error, "cachesize must be >= 20480"
347 e.open('.', db.DB_PRIVATE | db.DB_CREATE | db.DB_THREAD | db.DB_INIT_LOCK | db.DB_INIT_MPOOL)
348 return e
349
e = <DBEnv object>, e.open = <built-in method open of DBEnv object>, global db = <module '_bsddb' from '/opt/lib/python2.4/lib-dynload/_bsddb.so'>, db.DB_PRIVATE = 1048576, db.DB_CREATE = 1, db.DB_THREAD = 64, db.DB_INIT_LOCK = 8192, db.DB_INIT_MPOOL = 32768

DBInvalidArgError: (22, 'Invalid argument -- architecture lacks fast mutexes: applications cannot be threaded')
args = (22, 'Invalid argument -- architecture lacks fast mutexes: applications cannot be threaded')

Т.е. не поддерживаются какие то fast mutexes и поэтому proxymin не может открыть свою локальную базу данных.

Кто-нибудь знает - лечится ли это как нибудь?

zina79
22-04-2010, 18:32
Автор, если не трудно, обновите ссылки для скачивания. Спасибо.:)

Delirium
18-08-2010, 12:36
Всем привет.

Роутер wl500g подключен непосредственно к провайдеру и имеет выделенный статический IP. thttpd сервер работает отлично как на LAN так и на WAN.

Решил попробывать запустить на роутер простой HTTP сервер написанный на python. Вот его код:



from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler

import shutil
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):

f = StringIO()
f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
f.write("<html>\n<title>Test Page</title>\n")
f.write("<body>\n<h2>Hi</h2>\n")
f.write("</body></html>\n")

length = f.tell()
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(length))
self.end_headers()
f.seek(0)

self.wfile.write(f.read(length))


server_address = ('domain_name', 8666)
server = HTTPServer(server_address, MyHTTPRequestHandler)

while 1 == 1:
server.handle_request()


iptables -I INPUT 7 -p tcp --dport 8666 -j ACCEPT
прописано.

Он запускается и работает отлично в LAN. Но стоит зайти на него с WAN, всё сразу падает с Segmentation fault:



[delirium@Delirium_Router disc0_1]$ python server.py
92.241.190.197 - - [18/Aug/2010 15:16:17] "GET / HTTP/1.1" 200 -
92.241.190.197 - - [18/Aug/2010 15:16:20] "GET /favicon.ico HTTP/1.1" 200 -
92.241.190.197 - - [18/Aug/2010 15:17:00] "GET / HTTP/1.1" 200 -
92.241.190.197 - - [18/Aug/2010 15:17:03] "GET /favicon.ico HTTP/1.1" 200 -
Segmentation fault

(Первые два запроса из LAN, затем из WAN)

Версия python:
Python 2.5.5 (r255:77872, May 20 2010, 23:42:58)
[GCC 4.1.1] on linux2

Версия прошивки роутера: Olegs firmware 1.9.2.7-10

С чем это может быть связано? Куда копать?