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ć 😀
