وحدة Python مصممة لتنزيل الملفات من خلاصات RSS معينة، والتي تستهدف بشكل خاص ملفات podcast. لا يستخدم أي نوع من قواعد البيانات ولكنه يتطلب ملف تكوين.
تم تصميم البرنامج النصي ليتم تشغيله بشكل دوري. عند البدء، يقوم بتحليل الدليل الذي قام بتخزين الملفات التي تم تنزيلها مسبقًا. ثم يقوم بمقارنة هذه الملفات مع تلك المدرجة في موجز 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 -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 | خيط | لا | download_last | انظر في حالة وجود دليل فارغ |
podcast_extensions | قيمة المفتاح | لا | {".mp3": "audio/mpeg"} | راجع مرشح أنواع الملفات |
podcasts | القسم الفرعي | نعم | [] | انظر الفئة الفرعية للبودكاست |
http_headers | قيمة المفتاح | لا | {"User-Agent": "podcast-downloader"} | راجع رؤوس طلب HTTP |
fill_up_gaps | منطقية | لا | خطأ شنيع | راجع تنزيل الملفات من الثغرات |
download_delay | رقم | لا | 0 | راجع تأخير التنزيل |
يعد مقطع podcasts
جزءًا من ملف التكوين حيث تقوم بتزويد مجموعة من الكائنات بمحتوى مرتّب:
ملكية | يكتب | مطلوب | تقصير | ملحوظة |
---|---|---|---|---|
name | خيط | نعم | - | اسم القناة (استخدمها في المسجل) |
rss_link | خيط | نعم | - | عنوان URL لخلاصة RSS |
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). قد يؤدي هذا إلى مشاكل مثل: 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
and Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
.
عندما يكون لديك الكثير من الملفات لتنزيلها من خادم واحد، فقد يكون من الأفضل إعداد تأخير بسيط بين التنزيلات لتجنب التعرف على الخادم كمهاجم. يوجد في البرنامج النصي خيار يسمى 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
. ولتغييره، يمكنك توفير الحرف الجديد بعد :
(الحرف :). يحترم البرنامج النصي رموز معيار C لعام 1989، ولكن يجب استبدال علامة النسبة المئوية ( %
) بعلامة الدولار ( $
). هذا بسبب قراري المؤسف باستخدام حرف النسبة المئوية كعلامة للكود.
الرمز القياسي | رمز البرنامج النصي | ملحوظات |
---|---|---|
%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
يعني أنه سيتم تنزيل أحدث خمس حلقات.
سيقوم البرنامج النصي بتنزيل جميع الحلقات التي تظهر في الأيام الأخيرة. يمكن استخدامه عند التنزيل وفقًا لجدول زمني منتظم. يتم إعطاء الرقم 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
.
يبحث البرنامج النصي في جميع عقد items
في ملف RSS. يمكن أن تحتوي عقدة item
على عقدة enclosure
. يتم استخدام هذه العقد لتمرير الملفات. وفقًا للاتفاقية، يجب أن يحتوي item
الفردي على 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