用 Python 構建你自己的 RSS 提示系統

Clément Verna發表於2018-03-22

人生苦短,我用 Python,Python 是非常棒的快速構建應用程式的程式語言。在這篇文章中我們將學習如何使用 Python 去構建一個 RSS 提示系統,目標是使用 Fedora 快樂地學習 Python。如果你正在尋找一個完整的 RSS 提示應用程式,在 Fedora 中已經準備好了幾個包。

Fedora 和 Python —— 入門知識

Python 3.6 在 Fedora 中是預設安裝的,它包含了 Python 的很多標準庫。標準庫提供了一些可以讓我們的任務更加簡單完成的模組的集合。例如,在我們的案例中,我們將使用 sqlite3 模組在資料庫中去建立表、新增和讀取資料。在這個案例中,我們試圖去解決的是這樣的一個特定問題,在標準庫中沒有包含,而有可能已經有人為我們開發了這樣一個模組。最好是使用像大家熟知的 PyPI Python 包索引去搜尋一下。在我們的示例中,我們將使用 feedparser 去解析 RSS 源。

因為 feedparser 並不是標準庫,我們需要將它安裝到我們的系統上。幸運的是,在 Fedora 中有這個 RPM 包,因此,我們可以執行如下的命令去安裝 feedparser:

$ sudo dnf install python3-feedparser

我們現在已經擁有了編寫我們的應用程式所需的東西了。

儲存源資料

我們需要儲存已經發布的文章的資料,這樣我們的系統就可以只提示新發布的文章。我們要儲存的資料將是用來辨別一篇文章的唯一方法。因此,我們將儲存文章的標題和釋出日期。

因此,我們來使用 Python sqlite3 模組和一個簡單的 SQL 語句來建立我們的資料庫。同時也新增一些後面將要用到的模組(feedparse,smtplib,和 email)。

建立資料庫

#!/usr/bin/python3
import sqlite3
import smtplib
from email.mime.text import MIMEText

import feedparser

db_connection = sqlite3.connect('/var/tmp/magazine_rss.sqlite')
db = db_connection.cursor()
db.execute(' CREATE TABLE IF NOT EXISTS magazine (title TEXT, date TEXT)')

這幾行程式碼建立一個名為 magazine_rss.sqlite 檔案的新 sqlite 資料庫,然後在資料庫建立一個名為 magazine 的新表。這個表有兩個列 —— titledate —— 它們能存諸 TEXT 型別的資料,也就是說每個列的值都是文字字元。

檢查資料庫中的舊文章

由於我們僅希望增加新的文章到我們的資料庫中,因此我們需要一個功能去檢查 RSS 源中的文章在資料庫中是否存在。我們將根據它來判斷是否傳送(有新文章的)郵件提示。Ok,現在我們來寫這個功能的程式碼。

def article_is_not_db(article_title, article_date):
    """ Check if a given pair of article title and date
    is in the database.
    Args:
        article_title (str): The title of an article
        article_date  (str): The publication date of an article
    Return:
        True if the article is not in the database
        False if the article is already present in the database
    """
    db.execute("SELECT * from magazine WHERE title=? AND date=?", (article_title, article_date))
    if not db.fetchall():
        return True
    else:
        return False

這個功能的主要部分是一個 SQL 查詢,我們執行它去搜尋資料庫。我們使用一個 SELECT 命令去定義我們將要在哪個列上執行這個查詢。我們使用 * 符號去選取所有列(titledate)。然後,我們使用查詢的 WHERE 條件 article_titlearticle_date 去匹配標題和日期列中的值,以檢索出我們需要的內容。

最後,我們使用一個簡單的返回 True 或者 False 的邏輯來表示是否在資料庫中找到匹配的文章。

在資料庫中新增新文章

現在我們可以寫一些程式碼去新增新文章到資料庫中。

def add_article_to_db(article_title, article_date):
    """ Add a new article title and date to the database
    Args:
        article_title (str): The title of an article
        article_date (str): The publication date of an article
    """
    db.execute("INSERT INTO magazine VALUES (?,?)", (article_title, article_date))
    db_connection.commit()

這個功能很簡單,我們使用了一個 SQL 查詢去插入一個新行到 magazine 表的 article_titlearticle_date 列中。然後提交它到資料庫中永久儲存。

這些就是在資料庫中所需要的東西,接下來我們看一下,如何使用 Python 實現提示系統和傳送電子郵件。

傳送電子郵件提示

我們使用 Python 標準庫模組 smtplib 來建立一個傳送電子郵件的功能。我們也可以使用標準庫中的 email 模組去格式化我們的電子郵件資訊。

def send_notification(article_title, article_url):
    """ Add a new article title and date to the database

    Args:
        article_title (str): The title of an article
        article_url (str): The url to access the article
    """

    smtp_server = smtplib.SMTP('smtp.gmail.com', 587)
    smtp_server.ehlo()
    smtp_server.starttls()
    smtp_server.login('your_email@gmail.com', '123your_password')
    msg = MIMEText(f'\nHi there is a new Fedora Magazine article : {article_title}. \nYou can read it here {article_url}')
    msg['Subject'] = 'New Fedora Magazine Article Available'
    msg['From'] = 'your_email@gmail.com'
    msg['To'] = 'destination_email@gmail.com'
    smtp_server.send_message(msg)
    smtp_server.quit()

在這個示例中,我使用了谷歌郵件系統的 smtp 伺服器去傳送電子郵件,在你自己的程式碼中你需要將它更改為你自己的電子郵件服務提供者的 SMTP 伺服器。這個功能是個樣板,大多數的內容要根據你的 smtp 伺服器的引數來配置。程式碼中的電子郵件地址和憑證也要更改為你自己的。

如果在你的 Gmail 帳戶中使用了雙因子認證,那麼你需要配置一個密碼應用程式為你的這個應用程式提供一個唯一密碼。可以看這個 幫助頁面

讀取 Fedora Magazine 的 RSS 源

我們已經有了在資料庫中儲存文章和傳送提示電子郵件的功能,現在來建立一個解析 Fedora Magazine RSS 源並提取文章資料的功能。

def read_article_feed():
    """ Get articles from RSS feed """
    feed = feedparser.parse('https://fedoramagazine.org/feed/')
    for article in feed['entries']:
        if article_is_not_db(article['title'], article['published']):
            send_notification(article['title'], article['link'])
            add_article_to_db(article['title'], article['published'])

if __name__ == '__main__':
    read_article_feed()
    db_connection.close()

在這裡我們將使用 feedparser.parse 功能。這個功能返回一個用字典表示的 RSS 源,對於 feedparser 的完整描述可以參考它的 文件

RSS 源解析將返回最後的 10 篇文章作為 entries,然後我們提取以下資訊:標題、連結、文章釋出日期。因此,我們現在可以使用前面定義的檢查文章是否在資料庫中存在的功能,然後,傳送提示電子郵件並將這個文章新增到資料庫中。

當執行我們的指令碼時,最後的 if 語句執行我們的 read_article_feed 功能,然後關閉資料庫連線。

執行我們的指令碼

給指令碼檔案賦於正確執行許可權。接下來,我們使用 cron 實用程式去每小時自動執行一次我們的指令碼。cron 是一個作業計劃程式,我們可以使用它在一個固定的時間去執行一個任務。

$ chmod a+x my_rss_notifier.py
$ sudo cp my_rss_notifier.py /etc/cron.hourly

為了使該教程保持簡單,我們使用了 cron.hourly 目錄每小時執行一次我們的指令碼,如果你想學習關於 cron 的更多知識以及如何配置 crontab,請閱讀 cron 的 wikipedia 頁面

總結

在本教程中,我們學習瞭如何使用 Python 去建立一個簡單的 sqlite 資料庫、解析一個 RSS 源、以及傳送電子郵件。我希望透過這篇文章能夠向你展示,使用 Python 和 Fedora 構建你自己的應用程式是件多麼容易的事。

這個指令碼在 GitHub 上可以找到。


via: https://fedoramagazine.org/never-miss-magazines-article-build-rss-notification-system/

作者:Clément Verna 譯者:qhwdw 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

用 Python 構建你自己的 RSS 提示系統

相關文章