Chciałbym się „pochwalić” małym projekcikiem aplikacji do sprawdzania kanałów RSS i wysyłania ostatnich wpisów w mailu. Ja używam Feedly ale ostatnio doszkalam się z python i pomyślałem, że zrobię sobie taki mały projekcik 🙂 Będę go używał do ważniejszych kanałów RSS i będę miał bardziej zorganizowane artykuły do przeczytania. Ten projekt jest takim wstępem do czegoś większego. Mam pewien pomysł ale jak zrobię to napiszę 😉
Repozytorium znajduje się tutaj i jest też tam instrukcja jak używać. Jeśli coś dopisać to daj znać 😉
Do sprawdzania kanałów RSS używam biblioteki feedparser. Robię to w poniższy sposób. Tutaj taka mała uwaga modified
nie zawsze działa. To nie jest wina biblioteki a bardziej serwerów (z tego co wyczytałem w necie). Dlatego dodatkowo sprawdzam datę artykułu 😉
class FeedsReader: """Class representing a feeds reader""" def __init__(self, feed_urls) -> None: self.urls = feed_urls def get_feeds(self, from_date) -> []: """Function checks feeds and return posts since `from_date`.""" feeds = [] for url in self.urls: try: logging.info("Checking: %s since %s", url, from_date) d = feedparser.parse( url_file_stream_or_string=url, modified=from_date) feed = Feed(d.feed.title, d.feed.subtitle) length = len(d.entries) logging.info("Downloaded %d entries", length) for i, entry in enumerate(d.entries): logging.info( "Checking %d entry of [%s]", i + 1, d.feed.title) if datetime.datetime.fromtimestamp(mktime(entry.published_parsed)) >= from_date: feed.add_entry( entry.title, entry.summary, entry.link) feeds.append(feed) except Exception as e: logging.error("Something went wrong: %s", e, exc_info=True) continue return feeds
Jak już pobiorę artykuły/posty to wysyłam je w poniższy sposób. To co na pewno poprawię to szablon maila. W innych projektach używałem np. Sendgrid Więc może zrobię coś podobnego. Ale cierpliwości 😉
class EmailSender: """Class sends email with feeds""" def __init__(self, sender, receiver, smtp_host, smtp_port, smtp_user, smtp_password) -> None: self.sender = sender self.receiver = receiver self.smtp_host = smtp_host self.smtp_port = smtp_port self.smtp_user = smtp_user self.smtp_password = smtp_password def send_feeds_email(self, feeds) -> None: """Function sends email containing feeds' entries.""" body = self.create_email_body(feeds) mail = MIMEMultipart('alternative') mail['From'] = self.sender mail['To'] = self.receiver mail['Subject'] = "You latest feeds!" mail.attach(MIMEText("Switch to html", 'text')) mail.attach(MIMEText(body, 'html')) with smtplib.SMTP_SSL(self.smtp_host, self.smtp_port) as smtp_server: smtp_server.login(self.smtp_user, self.smtp_password) smtp_server.sendmail(self.sender, self.receiver, mail.as_string()) smtp_server.quit() def create_email_body(self, feeds) -> str: """Function create body of the feeds email.""" body = """ <!doctype html><html> <head></head> <body style="font-family: sans-serif;"><p><h1>Hello</h1><p>I think that you should read below articles ;-)</p> """ for feed in feeds: body = body + f'<h2>{feed.name}</h2><p><ul>' for entry in feed.entries: body = body + \ f'<li><a href="{entry.url}">{entry.title}</a><br />{entry.summary}</li>' body = body + '</ul></p>' return body + "</body></html>"
Przykładowy mail wygląda tak jak poniżej. Jak sam(a) widzisz style trzeba poprawić 😀