特定の RSS フィードからファイルをダウンロードするために設計された Python モジュール (特にポッドキャストを対象としています)。いかなる種類のデータベースも使用しませんが、構成ファイルが必要です。
スクリプトは定期的に実行されることを目的としています。起動すると、以前にダウンロードしたファイルが保存されていたディレクトリが分析されます。次に、これらのファイルを RSS フィードにリストされているファイルと比較し、不足しているファイルを特定してダウンロードします。
デフォルトで検索されるファイルはmp3
です。
空のディレクトリで以下の例を使用した結果は次のようになります。
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
結果:
dplocki@ghost-wheel:~$ tree podcasts/
podcasts/
├── RealPython
│ └── [20240405] rpp_e199_03_calvin.eef1db4d6679.mp3
└── SGTTU
└── skepticast2024-04-06.mp3
2 directories, 2 files
PyPI からのインストール:
pip install podcast_downloader
スクリプトが動作するには構成ファイルが必要です。インストール後、スクリプトは任意の Python モジュールとして実行できます。
python -m podcast_downloader
指定された構成ファイルを使用してスクリプトを実行することもできます。
python -m podcast_downloader --config my_config.json
設定ファイルの例
{
"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% "
}
]
}
デフォルトでは、設定ファイルはホーム ディレクトリに配置されます。ファイル名は.podcast_downloader_config.json
です。
設定ファイルはJSON形式です。予期されるエンコーディングは utf-8 です。
設定ファイルへのパスはスクリプトの引数で指定できます。
スクリプトは、デフォルト値を構成ファイルから読み取られた値に置き換えます。これらはコマンドラインから指定された値によってオーバーロードされます。
command line parameters > configuration file > default values
財産 | タイプ | 必須? | デフォルト | 注記 |
---|---|---|---|---|
downloads_limit | 番号 | いいえ | 無限大 | |
if_directory_empty | 弦 | いいえ | ダウンロード_最後 | 空のディレクトリの場合を参照してください。 |
podcast_extensions | キーと値 | いいえ | {".mp3": "audio/mpeg"} | 「ファイルタイプフィルター」を参照してください。 |
podcasts | サブセクション | はい | [] | ポッドキャストのサブカテゴリを参照してください |
http_headers | キーと値 | いいえ | {"User-Agent": "podcast-downloader"} | HTTP リクエストヘッダーを参照してください。 |
fill_up_gaps | ブール値 | いいえ | 間違い | 「ギャップからのファイルのダウンロード」を参照してください。 |
download_delay | 番号 | いいえ | 0 | 「ダウンロードの遅延」を参照してください。 |
podcasts
セグメントは、以下のコンテンツを含むオブジェクトの配列を提供する構成ファイルの一部です。
財産 | タイプ | 必須 | デフォルト | 注記 |
---|---|---|---|---|
name | 弦 | はい | - | チャネルの名前 (ロガーで使用) |
rss_link | 弦 | はい | - | RSSフィードのURL |
path | 弦 | はい | - | ポッドキャストが保存されているディレクトリへのパスがダウンロードされます |
file_name_template | 弦 | いいえ | %file_name%.%file_extension% | ダウンロードされたファイルのテンプレート。「ファイル名テンプレート」を参照してください。 |
disable | ブール値 | いいえ | false | このポッドキャストは無視されます |
podcast_extensions | キーと値 | いいえ | {".mp3": "audio/mpeg"} | ファイルフィルター |
if_directory_empty | 弦 | いいえ | download_last | 空のディレクトリの場合を参照してください。 |
require_date | ブール値 | いいえ | false | 非推奨ポッドキャストの日付をファイル名に追加する必要があります - file_name_template を使用します: [%publish_date%] %file_name%.%file_extension%" |
http_headers | キーと値 | いいえ | {"User-Agent": "podcast-downloader"} | HTTP リクエストヘッダーを参照してください。 |
fill_up_gaps | ブール値 | いいえ | 間違い | 「ギャップからのファイルのダウンロード」を参照してください。 |
一部のサーバーは、urllib 自体の表示方法 (HTTP User-Agent ヘッダー) を好まない場合があります。これにより、 urllib.error.HTTPError: HTTP Error 403: Forbidden
のような問題が発生する可能性があります。そのため、ファイルのダウンロード中に HTTP ヘッダーを指定することにより、スクリプトが別のものを装う可能性があります。
構成ファイルでhttp_headers
オプションを使用します。値は、各ヘッダーがキーと値のペアとして表示される辞書オブジェクトである必要があります。キーはヘッダーのタイトルで、値はヘッダーの値です。
デフォルトでは、値は{"User-Agent": "podcast-downloader"}
です。 http_headers
に他の値を指定すると、すべてのデフォルト値がオーバーライドされます (これらはマージされません)。
一方、ポッドキャストのサブ構成では、 http_headers
グローバルhttp_headers
とマージされます。競合が発生した場合 (同じキー名)、ポッドキャストのサブ設定の値がグローバルの値をオーバーライドします。
例:
{
"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== "
}
}
]
}
この例では、Unua Podcast はヘッダーUser-Agent: Mozilla/5.0
のみでダウンロードされ、Dua Podcast はUser-Agent: podcast-downloader
およびAuthorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
でダウンロードされます。
1 つのサーバーから大量のファイルをダウンロードする場合は、サーバーによって攻撃者として認識されるのを避けるために、ダウンロード間にわずかな遅延を設定する方がよい場合があります。スクリプトには、 download_delay
というオプションがあります。これは、スクリプトがダウンロードの間に待機する秒数を表します。
デフォルト値は0
です。
注:
スクリプトは次のコマンド ライン引数を受け入れます。
ショートバージョン | 長い名前 | パラメータ | デフォルト | 注記 |
---|---|---|---|---|
--config | 弦 | ~/.podcast_downloader_config.json | 設定ファイルの配置 | |
--downloads_limit | 番号 | 無限大 | ダウンロードできるmp3ファイルの最大数 | |
--if_directory_empty | 弦 | download_last | 空のディレクトリに対する一般的なアプローチ | |
--download_delay | 番号 | 0 | ダウンロード間の待ち時間 (秒) |
ダウンロード後にファイル名を調整する場合に使用します。
デフォルト値 ( %file_name%.%file_extension%
) は、元の作成者によってアップロードされたファイルを単純に保存します。ファイル名とその拡張子は、ポッドキャスト ファイルへのリンクに基づいています。
テンプレートの値:
名前 | 注意事項 |
---|---|
%file_name% | リンクからのファイル名(拡張子なし) |
%file_extension% | ファイルの拡張子(リンクから) |
%publish_date% | RSS エントリの公開日 |
%title% | RSSエントリのタイトル |
%publish_date%
はデフォルトでYEARMMDD
形式で結果を返します。これを変更するには、コロン ( :
文字) の後に新しいものを指定します。このスクリプトは 1989 C 標準のコードを尊重しますが、パーセント記号 ( %
) はドル記号 ( $
) に置き換える必要があります。これは、コードのマーカーとしてパーセント文字を使用するという私の不運な決定によるものです。
標準コード | スクリプトコード | 注意事項 |
---|---|---|
%Y%m%d | $Y$m$d | %publish_date% のデフォルト値 |
%A | $A | 曜日を追加(現地言語設定) |
%x | $x | 現地の日付を表します。警告: 一部の設定では、ここで/ が使用されているため、ファイル名に問題が発生する可能性があります。 |
[%publish_date%] %file_name%.%file_extension%
[%publish_date%] %title%.%file_extension%
ポッドキャストはほとんどの場合、 *.mp3
ファイルとして保存されます。デフォルトでは、Podcast Downloader はそれらのタイプのみを検索し、他のタイプはすべて無視します。
ポッドキャストが他のタイプのメディア ファイルをサポートしている場合は、ファイル フィルターを指定できます。ファイルの拡張子 ( .mp3
など) と RSS フィード自体のリンクの種類 ( mp3
の場合はaudio/mpeg
) を指定します。
ファイルの種類がわからない場合は、RSS ファイルで検索できます。 enclosure
タグを検索すると、次のようになります。
< enclosure url = " https://www.vidocast.url/podcast/episode23.m4a " length = " 14527149 " type = " audio/x-m4a " />
注: ファイル拡張子のドットは必須です。
"podcast_extensions" : {
".mp3" : " audio/mpeg " ,
".m4a" : " audio/x-m4a "
}
ポッドキャストのディレクトリが空の場合、スクリプトは何をすべきかを認識する必要があります。データベースがないため、次のことが可能です。
デフォルトの動作は次のとおりです: download_last
スクリプトはフィードからすべてのエピソードをダウンロードします。
download_all_from_feed
によって設定されます。
スクリプトはフィードから最後のエピソードのみをダウンロードします。これはスクリプトのデフォルトのアプローチでもあります。
download_last
によって設定されます。
スクリプトは、指定された数のエピソードをフィードから正確にダウンロードします。
download_last_n_episodes
によって設定されます。 n は、ダウンロードしたいエピソードの数に置き換える必要があります。たとえば、 download_last_5_episodes
、最新の 5 つのエピソードがダウンロードされることを意味します。
スクリプトは、最近n日間に表示されたすべてのエピソードをダウンロードします。定期的にダウンロードする場合に使用できます。 n の数値は、セットアップ値download_from_n_days
内で指定されます。例: download_from_3_days
、過去 3 日間のすべてのエピソードをダウンロードすることを意味します。
スクリプトは、最終エピソードのリリース日以降に表示されるすべてのエピソードをダウンロードします。
n番号は通常のエピソードの日です。ここに曜日を単語として指定できます(文字のサイズは無視されます)。
全日制 | 短縮名 |
---|---|
月曜日 | 月 |
火曜日 | 火曜日 |
水曜日 | 水曜日 |
木曜日 | 木曜日 |
金曜日 | 金 |
土曜日 | 土 |
日曜日 | 太陽 |
数字を指定すると、その月の日を意味します。スクリプトは 1 ~ 28 の数値のみを受け入れます。
download_from_
によって設定されます。
例:
値の例 | 意味 |
---|---|
download_from_monday | 新しいエピソードは月曜日に登場します。スクリプトは、先週の火曜日以降のすべてのエピソード (それを含む) をダウンロードします。 |
download_from_Fri | 新しいエピソードは金曜日に登場します。スクリプトは先週の土曜日以降のすべてのエピソード (それを含む) をダウンロードします。 |
download_from_12 | 新しいエピソードは毎月 12 日に登場します。スクリプトは 13 か月前以降のすべてのエピソードをダウンロードします |
トーテム ファイルを作成すると、スクリプトはそれを使用して最後の実行日を保存できます。次に、この日付に基づいて、スクリプトはそれ以降に登場したすべての新しいエピソードをダウンロードします。
download_since_last_run
によって設定されます。 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 "
}
]
}
スクリプトはファイルの最終変更日を読み取ります。ファイルの変更日はスクリプトによって更新されます。
スクリプトは、(フィード データに基づいて) ダウンロードされたファイルのストリームを認識します。デフォルトでは、最後にダウンロードされたファイル (フィードによる) がダウンロードの開始をマークします。ギャップがある場合、つまり最後にダウンロードされたファイルより前に欠落しているファイルがある場合、スクリプトはデフォルトでそれらを無視します。ただし、既にダウンロードされているファイルの間に不足しているファイルをすべてダウンロードするようにこの動作を変更する可能性があります。これを有効にするには、 fill_up_gaps
値をtrueに設定する必要があります。スクリプトは、(フィードによると) 最初のエピソード、つまり最も前のエピソードより前にファイルをダウンロードしないことに注意することが重要です。
デフォルト値: false
。
スクリプトは、RSS ファイル内のすべてのitems
ノードを調べます。 item
ノードにはenclosure
ノードを含めることができます。これらのノードはファイルの受け渡しに慣れています。規則によれば、単一のitem
は 1 つのenclosure
のみが含まれるべきですが、スクリプト (その下で使用されるライブラリとして) はポッドキャストitem
に添付された複数のファイルを処理できます。
OPML ファイルは構成に変換できます。出力ファイルを調整する必要があります ( 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 )
使用例 ( opml_converter.py
として保存した後):
python opml_converter.py example.opml > podcast_downloader_config.json