โมดูล Python ได้รับการออกแบบมาเพื่อดาวน์โหลดไฟล์จากฟีด RSS ที่กำหนด โดยมีเป้าหมายเฉพาะที่พอดแคสต์ ไม่ได้ใช้ฐานข้อมูลประเภทใด ๆ แต่ต้องใช้ไฟล์กำหนดค่า
สคริปต์นี้มีวัตถุประสงค์เพื่อให้ทำงานเป็นระยะ เมื่อเริ่มต้นระบบจะวิเคราะห์ไดเร็กทอรีที่จัดเก็บไฟล์ที่ดาวน์โหลดไว้ก่อนหน้านี้ จากนั้นจะเปรียบเทียบไฟล์เหล่านี้กับไฟล์ที่อยู่ในฟีด 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 "<none>"
[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 "<none>"
[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 | เชือก | ใช่ | - | ชื่อช่อง (ใช้ใน Logger) |
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 User-Agent) สิ่งนี้อาจทำให้เกิดปัญหาเช่น: urllib.error.HTTPError: HTTP Error 403: Forbidden
ด้วยเหตุนี้ จึงเป็นไปได้ที่สคริปต์จะแสดงเป็นอย่างอื่น: โดยการระบุส่วนหัว HTTP ระหว่างการดาวน์โหลดไฟล์
ใช้ตัวเลือก http_headers
ในไฟล์การกำหนดค่า ค่าควรเป็นออบเจ็กต์พจนานุกรมโดยแต่ละส่วนหัวจะแสดงเป็นคู่คีย์-ค่า คีย์เป็นชื่อส่วนหัวและค่าเป็นค่าส่วนหัว
โดยค่าเริ่มต้น ค่าจะเป็น: {"User-Agent": "podcast-downloader"}
การระบุสิ่งอื่นใดสำหรับ http_headers
จะแทนที่ค่าเริ่มต้นทั้งหมด (ไม่รวมกัน)
ในทางกลับกัน ในการกำหนดค่าย่อยของพอดแคสต์ http_headers
จะถูกรวมเข้ากับ http_headers
ส่วนกลาง ในกรณีที่มีข้อขัดแย้ง (ชื่อคีย์เดียวกัน) Vale จากการกำหนดค่าย่อยของพอดแคสต์จะแทนที่การกำหนดค่าส่วนกลาง
ตัวอย่าง:
{
"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==
เมื่อคุณมีไฟล์จำนวนมากให้ดาวน์โหลดจากเซิร์ฟเวอร์เดียว อาจเป็นการดีกว่าถ้าตั้งค่าการหน่วงเวลาเล็กน้อยระหว่างการดาวน์โหลดเพื่อหลีกเลี่ยงไม่ให้เซิร์ฟเวอร์รับรู้ว่าเป็นผู้โจมตี ในสคริปต์มีตัวเลือกที่เรียกว่า 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
หมายความว่าจะมีการดาวน์โหลดตอนล่าสุดห้าตอน
สคริปต์จะดาวน์โหลดตอนทั้งหมดที่ปรากฏในช่วง 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
สคริปต์จะตรวจสอบโหนด 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