El módulo de Python diseñado para descargar archivos de canales RSS determinados, especialmente dirigido a podcasts. No utiliza ningún tipo de base de datos pero requiere un archivo de configuración.
El script está pensado para ejecutarse periódicamente. Al iniciar, analiza el directorio donde almacenó previamente los archivos descargados. Luego compara estos archivos con los que figuran en la fuente RSS, identifica los que faltan y los descarga.
Los archivos buscados por defecto son mp3
.
El resultado de utilizar el siguiente ejemplo, en directorios vacíos, será:
dplocki@ghost-wheel:~$ python -m podcast_downloader
[2024-04-08 21:19:10] Loading configuration (from file: "~/.podcast_downloader_config.json")
[2024-04-08 21:19:15] Checking "The Skeptic Guide"
[2024-04-08 21:19:15] Last downloaded file ""
[2024-04-08 21:19:15] The Skeptic Guide: Downloading file: "https://traffic.libsyn.com/secure/skepticsguide/skepticast2024-04-06.mp3" saved as "skepticast2024-04-06.mp3"
[2024-04-08 21:19:41] Checking "The Real Python Podcast"
[2024-04-08 21:19:41] Last downloaded file ""
[2024-04-08 21:19:41] The Real Python Podcast: Downloading file: "https://chtbl.com/track/92DB94/files.realpython.com/podcasts/RPP_E199_03_Calvin.eef1db4d6679.mp3" saved as "[20240405] rpp_e199_03_calvin.eef1db4d6679.mp3"
[2024-04-08 21:20:04] Finished
El resultado:
dplocki@ghost-wheel:~$ tree podcasts/
podcasts/
├── RealPython
│ └── [20240405] rpp_e199_03_calvin.eef1db4d6679.mp3
└── SGTTU
└── skepticast2024-04-06.mp3
2 directories, 2 files
Instalación desde PyPI:
pip install podcast_downloader
El script requiere un archivo de configuración para funcionar. Después de la instalación, el script se puede ejecutar como cualquier módulo de Python:
python -m podcast_downloader
También es posible ejecutar el script con el archivo de configuración dado:
python -m podcast_downloader --config my_config.json
Un ejemplo de archivo de configuración
{
"if_directory_empty" : " download_from_4_days " ,
"podcasts" : [
{
"name" : " The Skeptic Guide " ,
"rss_link" : " https://feed.theskepticsguide.org/feed/rss.aspx " ,
"path" : " ~/podcasts/SGTTU "
},
{
"rss_link" : " https://realpython.com/podcasts/rpp/feed " ,
"path" : " ~/podcasts/RealPython " ,
"file_name_template" : " [%publish_date%] %file_name%.%file_extension% "
}
]
}
De forma predeterminada, el archivo de configuración se coloca en el directorio de inicio. Su nombre de archivo es: .podcast_downloader_config.json
.
El archivo de configuración tiene el formato JSON. La codificación esperada es utf-8.
La ruta al archivo de configuración se puede especificar mediante el argumento del script.
El script reemplaza los valores predeterminados por los leídos del archivo de configuración. Estos estarán sobrecargados por los valores proporcionados desde la línea de comando.
command line parameters > configuration file > default values
Propiedad | Tipo | ¿Requerido? | Por defecto | Nota |
---|---|---|---|---|
downloads_limit | número | No | infinidad | |
if_directory_empty | cadena | No | descarga_última | Ver En caso de directorio vacío |
podcast_extensions | valor-clave | No | {".mp3": "audio/mpeg"} | Ver filtro de tipos de archivos |
podcasts | subsección | Sí | [] | Ver subcategoría Podcasts |
http_headers | valor-clave | No | {"User-Agent": "podcast-downloader"} | Ver encabezados de solicitud HTTP |
fill_up_gaps | booleano | No | FALSO | Ver Descargar archivos desde huecos |
download_delay | número | No | 0 | Ver retraso en la descarga |
El segmento podcasts
es la parte del archivo de configuración donde proporciona la matriz de objetos con el siguiente contenido:
Propiedad | Tipo | Requerido | Por defecto | Nota |
---|---|---|---|---|
name | cadena | Sí | - | El nombre del canal (usar en el registrador) |
rss_link | cadena | Sí | - | La URL del feed RSS |
path | cadena | Sí | - | Se descargará la ruta al directorio donde se almacenan los podcasts. |
file_name_template | cadena | No | %file_name%.%file_extension% | La plantilla para los archivos descargados, consulte Plantilla de nombre de archivo. |
disable | booleano | No | false | Este podcast será ignorado. |
podcast_extensions | valor-clave | No | {".mp3": "audio/mpeg"} | El filtro de archivos |
if_directory_empty | cadena | No | download_last | Ver En caso de directorio vacío |
require_date | booleano | No | false | En desuso La fecha del podcast debe agregarse al nombre del archivo; use file_name_template : [%publish_date%] %file_name%.%file_extension%" |
http_headers | valor-clave | No | {"User-Agent": "podcast-downloader"} | Ver encabezados de solicitud HTTP |
fill_up_gaps | booleano | No | FALSO | Ver Descargar archivos desde huecos |
Es posible que a algunos servidores no les guste cómo se les presenta la urllib (el encabezado HTTP User-Agent). Esto puede provocar problemas como: urllib.error.HTTPError: HTTP Error 403: Forbidden
. Por eso, existe la posibilidad de que el script se haga pasar por otra cosa: especificando los encabezados HTTP durante la descarga de archivos.
Utilice la opción http_headers
en el archivo de configuración. El valor debe ser un objeto de diccionario donde cada encabezado se presente como un par clave-valor. La clave es el título del encabezado y el valor es el valor del encabezado.
Por defecto el valor es: {"User-Agent": "podcast-downloader"}
. Proporcionar cualquier otra cosa para http_headers
anulará todos los valores predeterminados (no se fusionan).
Por otro lado, en la subconfiguración del podcast, los http_headers
se fusionarán con los http_headers
globales. En caso de conflicto (mismo nombre de clave), el valor de la subconfiguración del podcast anulará el global.
Ejemplo:
{
"http_headers" : {
"User-Agent" : " podcast-downloader "
},
"podcasts" : [
{
"name" : " Unua Podcast " ,
"rss_link" : " http://www.unuapodcast.org/feed.rss " ,
"path" : " ~/podcasts/unua_podcast " ,
"https_headers" : {
"User-Agent" : " Mozilla/5.0 "
}
},
{
"name" : " Dua Podcast " ,
"rss_link" : " http://www.duapodcast.org/feed.rss " ,
"path" : " ~/podcasts/dua_podcast " ,
"https_headers" : {
"Authorization" : " Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== "
}
}
]
}
En este ejemplo, el Unua Podcast se descargará solo con el encabezado: User-Agent: Mozilla/5.0
y el Dua Podcast con: User-Agent: podcast-downloader
y Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
.
Cuando tenga que descargar muchos archivos desde un solo servidor, puede ser mejor configurar un pequeño retraso entre descargas para evitar que el servidor lo reconozca como un atacante. En el script hay una opción llamada download_delay
, que representa la cantidad de segundos que el script esperará entre descargas.
El valor predeterminado es 0
.
Notas:
El script acepta los siguientes argumentos de línea de comando:
Versión corta | nombre largo | Parámetro | Por defecto | Nota |
---|---|---|---|---|
--config | cadena | ~/.podcast_downloader_config.json | La ubicación del archivo de configuración. | |
--downloads_limit | número | infinidad | El número máximo de archivos mp3 descargados. | |
--if_directory_empty | cadena | download_last | El enfoque general en un directorio vacío. | |
--download_delay | número | 0 | El tiempo de espera (segundos) entre descargas. |
Úselo para ajustar el nombre del archivo después de la descarga.
El valor predeterminado ( %file_name%.%file_extension%
) simplemente guardará el archivo tal como lo subió el creador original. El nombre del archivo y su extensión se basan en el enlace al archivo podcast.
Valores de plantilla:
Nombre | Notas |
---|---|
%file_name% | El nombre del archivo del enlace, sin extensión. |
%file_extension% | La extensión del archivo, desde el enlace. |
%publish_date% | La fecha de publicación de la entrada RSS. |
%title% | El título de la entrada RSS. |
%publish_date%
por defecto da el resultado en formato YEARMMDD
. Para cambiarlo, puede proporcionar uno nuevo después de los dos puntos ( :
carácter:). El script respeta los códigos de la norma C de 1989, pero el signo de porcentaje ( %
) debe ser reemplazado por el signo de dólar ( $
). Esto se debe a mi desafortunada decisión de utilizar el carácter de porcentaje como marcador del código.
El código estándar | El código del guión | Notas |
---|---|---|
%Y%m%d | $Y$m$d | El valor predeterminado de %publish_date% |
%A | $A | Agrega el día de la semana (configuración de idioma local) |
%x | $x | La fecha local representa. Advertencia : en algunas configuraciones, / se usa aquí, por lo que puede causar problemas en el nombre del archivo |
[%publish_date%] %file_name%.%file_extension%
[%publish_date%] %title%.%file_extension%
Los podcasts se almacenan principalmente como archivos *.mp3
. De forma predeterminada, Podcast Downloader busca solo ellos, ignorando todos los demás tipos.
Si su podcast admite otros tipos de archivos multimedia, puede especificar los filtros de archivos. Proporcione la extensión del archivo (como .mp3
) y el tipo de enlace en la fuente RSS (para mp3
es audio/mpeg
).
Si no conoce el tipo de archivo, puede buscarlo en el archivo RSS. Busque etiquetas enclosure
, debería verse así:
< enclosure url = " https://www.vidocast.url/podcast/episode23.m4a " length = " 14527149 " type = " audio/x-m4a " />
Nota : el punto en la extensión del archivo es obligatorio.
"podcast_extensions" : {
".mp3" : " audio/mpeg " ,
".m4a" : " audio/x-m4a "
}
Si un directorio de podcast está vacío, el script necesita saber qué hacer. Por falta de base de datos, puedes:
El comportamiento predeterminado es: download_last
El guión descargará todos los episodios del feed.
Establecido por download_all_from_feed
.
El guión descargará solo el último episodio del feed. También es el enfoque predeterminado del script.
Establecido por download_last
.
El guión descargará exactamente la cantidad indicada de episodios del feed.
Establecido por download_last_n_episodes
. La n debe ser reemplazada por una cantidad de episodios que deseaba descargar. Por ejemplo: download_last_5_episodes
significa que se descargarán los cinco episodios más recientes.
El guión descargará todos los episodios que aparezcan en los últimos n días. Se puede utilizar cuando se descarga según el horario habitual. El número n se proporciona dentro del valor de configuración: download_from_n_days
. Por ejemplo: download_from_3_days
significa descargar todos los episodios de los últimos 3 días.
El guión descargará todos los episodios que aparezcan después del día de lanzamiento del último episodio.
El número n es el día del episodio normal. Puede proporcionar aquí los días de la semana como palabra (se ignora el tamaño de las letras)
día de semana completo | Acortar nombre |
---|---|
Lunes | Lun |
Martes | martes |
Miércoles | casarse |
Jueves | jueves |
Viernes | Vie |
Sábado | Se sentó |
Domingo | Sol |
Puede proporcionar el número, significará el día del mes. El script acepta sólo números del 1 al 28.
Establecido por download_from_
.
Ejemplos:
Valor de ejemplo | Significado |
---|---|
download_from_monday | Los nuevos episodios aparecen el lunes. El guión descargará todos los episodios desde el pasado martes (incluido él) |
download_from_Fri | Los nuevos episodios aparecen el viernes. El guión descargará todos los episodios desde el pasado sábado (incluido este) |
download_from_12 | Aparecen nuevos episodios cada día 12 del mes. El guión descargará todos los episodios desde el mes 13 antes. |
Una vez que establezca el archivo tótem, el script puede usarlo para almacenar la fecha de su última ejecución. Luego, según esta fecha, el guión descargará todos los episodios nuevos que hayan aparecido desde entonces.
Establecido por download_since_last_run
. Requiere establecer el archivo de almacenamiento mediante last_run_mark_file_path
.
{
"last_run_mark_file_path" : " ~/.totem.json " ,
"podcasts" : [
{
"name" : " The Skeptic Guide " ,
"rss_link" : " https://feed.theskepticsguide.org/feed/rss.aspx " ,
"path" : " ~/podcasts/SGTTU "
}
]
}
El script lee la fecha de la última modificación del archivo. La fecha de modificación del archivo se actualiza mediante el script.
El script reconoce el flujo de archivos descargados (según los datos del feed). De forma predeterminada, el último archivo descargado (según el feed) marca el inicio de la descarga. En caso de espacios vacíos, situación en la que faltan archivos antes del último descargado, el script los ignorará de forma predeterminada. Sin embargo, existe la posibilidad de cambiar este comportamiento para descargar todos los archivos que faltan entre los ya descargados. Para habilitar esto, debe establecer el valor fill_up_gaps
en verdadero . Es importante tener en cuenta que el guión no descargará archivos antes del primero (según el feed), el episodio más anterior.
Valor predeterminado: false
.
El script examina todos los nodos items
del archivo RSS. El nodo item
puede contener el nodo enclosure
. Esos nodos están acostumbrados a pasar los archivos. Según la convención, el item
único debe contener solo un enclosure
, pero el script (como la biblioteca utilizada en él) puede manejar los múltiples archivos adjuntos al item
del podcast.
Los archivos OPML se pueden convertir en configuración. Es necesario ajustar el archivo de salida (falta la path
).
import json
import sys
import xml . etree . ElementTree as ET
def build_podcast ( node_rss ):
return {
"name" : node_rss . attrib [ "title" ],
"rss_link" : node_rss . attrib [ "xmlUrl" ],
"path" : "" ,
}
tree = ET . parse ( sys . argv [ 1 ])
podcasts = list ( map ( build_podcast , tree . findall ( "body/outline[@type='rss']" )))
result = json . dumps ({ "podcasts" : podcasts }, sort_keys = True , indent = 4 )
print ( result )
Ejemplo de uso (después de guardarlo como opml_converter.py
):
python opml_converter.py example.opml > podcast_downloader_config.json