שלום אורח התחבר

בואו נמצא פודקסטים מעניינים עם פייתון

נושאים:יומי

במכונית, בסופר או כשעושים כלים, כולם אוהבים לשמוע פודקסטים. מתוך סקרנות ובשביל למצוא פודקסטים מעניינים בעברית הגעתי לאתר המעולה podcastim.org.il ומצאתי שם רשימה אין סופית כמעט של פודקסטים בעברית. יש להם שם גם תיבה של חיפוש אבל מה שאותי הכי עניין זה למצוא פודקסטים שעדיין מפרסמים פרקים חדשים, רצוי כל שבוע.

אין עדיין רשימה כזאת מוכנה בפודקסטים אבל עם פייתון וקצת רצון טוב אפשר למצוא אותה בקלות.

1התקנת הכלים

בכל דף פודקסט באתר יש רשימה של פרקים שהוקלטו, ובדף הראשי רשימה של כל הפודקסטים. עם הספריה aiohttp אוכל בקלות להוציא בקשות http ועם beautifulsoup4 נקרא את ה HTML-ים ונשלוף מהם את המידע שצריך. בצד ההשלמות beautifulsoup עובדת טוב יותר עם ספריית lxml והספריה asyncio_throttle שומרת שלא נעמיס על האתר עם יותר מדי בקשות במקביל. סך הכל שורת ההתקנה:

$ pip install aiohttp[speedups] beautifulsoup4 lxml asyncio_throttle

2איך יודעים אם פודקסט העלה פרק בשבועיים האחרונים

בכל דף פודקסט באתר יש רשימה של פרקים שהפודקסט פירסם. הפקודה fetch של aiohttp מביאה תוכן של עמוד אינטרנט, הפקודה select של beautifulsoup שולפת מידע מהדף ויחד הקוד הבא נכנס לדף פודקסט, מוציא את התאריך בו התפרסם הפרק האחרון ומדפיס אותו רק אם הפרק האחרון פורסם בשבועיים האחרונים:

async def check_podcast(session, podcast_url, podcast_name):
    html = await fetch(session, podcast_url)
    soup = BeautifulSoup(html, 'lxml')
    dates = soup.select('.episode-list__entry .pod-entry__date')
    if len(dates) > 0:
        last_episode_date = datetime.datetime.strptime(dates[0].get_text(), '%b %d, %Y')

        if (datetime.datetime.now() - last_episode_date).days < 14:
            print(podcast_name, podcast_url)

3רשימת כל הפודקסטים

באותו האופן אפשר לקחת את הדף הראשי ולמשוך ממנו את רשימת כל הפודקסטים:

html = await fetch(session, 'https://podcastim.org.il/')
soup = BeautifulSoup(html, 'lxml')
titles = soup.select('.pt-cv-title a')

ואולי החלק הכי מורכב בתוכנית היא הלולאה הבאה שמפעילה את check_podcast במקביל על כל רשימת הפודקסטים, וסומכת על asyncio_throttler כדי לא להעמיס על האתר:

await asyncio.wait([check_podcast(session, link.get('href'), link.get_text()) for link in titles])

הפקודה asyncio.wait מקבלת רשימה של דברים שאפשר לחכות להם ומאחדת אותם ל"משימה" אחת. הפקודה await ממתינה לביצוע משימה זו והפונקציה check_podcast היא שיוצרת את המשימה. ה for מתחבא בסוף השורה והוא שמציין שאנחנו בלולאה, לולאה מסוג List Comprehension.

בקיצור הנה התוכנית אליה הגעתי בסוף שתדפיס לכם רשימה של כל הפודקסטים שפירסמו פרק חדש בשבועיים האחרונים:

import aiohttp
import asyncio
from bs4 import BeautifulSoup
import pdb
from asyncio_throttle import Throttler
import datetime


async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def check_podcast(session, podcast_url, podcast_name):
    html = await fetch(session, podcast_url)
    soup = BeautifulSoup(html, 'lxml')
    dates = soup.select('.episode-list__entry .pod-entry__date')
    if len(dates) > 0:
        last_episode_date = datetime.datetime.strptime(dates[0].get_text(), '%b %d, %Y')

        if (datetime.datetime.now() - last_episode_date).days < 14:
            print(podcast_name, podcast_url)

throttler = Throttler(rate_limit=30, period=60)

async def main():
    async with throttler:
        async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session:
            html = await fetch(session, 'https://podcastim.org.il/')
            soup = BeautifulSoup(html, 'lxml')
            titles = soup.select('.pt-cv-title a')
            await asyncio.wait([check_podcast(session, link.get('href'), link.get_text()) for link in titles])

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

האזנה נעימה.

מעדיפים לקרוא מהטלגרם? בקרו אותנו ב:@tocodeil

או הזינו את כתובת המייל וקבלו את הפוסט היומי בכל בוקר אליכם לתיבה:


נהניתם מהפוסט? מוזמנים לשתף ולהגיב