Make.

Kindleやスマホにニュースを送信

Pocket

Raspberry Piで決まった時間にニュースを送る方法を解説します。
Raspberry Piに限らず、WindowsやMacでも可能ですが、Raspberry Piは消費電力が少ないため、簡単なサーバーとして動かす有用性が生きてきます。

Raspberry Piは、つけっぱなしでも電気代は、一ヶ月程で50円程度くらいになります。
ここではRaspberry Piの電源を常時つけて、決まった時間にKindleへニュースを送ります。
また、Kindleへの送信だけでなく、メールが受信できる環境であれば、ニュースの自分のスマートフォンなどへ送ることができます。


kindleについて

kindleはAmazonで購入した本を読むだけでなく、ユーザが好きなファイルをkindleに送り閲覧することができます。kindleは、Word、HTML、MOBI、ePub、RTF、TXT、Adobe PDFといった多彩なフィアル形式をサポートしています。

Kindleを購入する人は、Wifiモデルを購入する人が多いようです。3Gモデルならば、自宅外でもコンテンツのダウンロードが行えますが、Wifiモデルでは行えません。また、ネットワーク通信を使うと、バッテリの消耗が激しいため、Wifiモデルであろうとネットで最新のニュースを閲覧するには、Kindleは向いていません。
そのため、ここでは毎朝、RaspberryPi上でプログラムを実行させ、Kindleに向けてニュースを送信します。これにより、通勤途中の電車の中で、Kindleを使い、ニュースを読むことができるようになります。

ここでは、英語の勉強もかねて、英語のニュースをkindleに送るプログラムを作成します。
英語のニュースは、JapanTodayから取得します。
JapanTodayのニュースは、比較的簡単で短いので、英語の勉強に最適かと思います。


Kindleの設定

Kindleにメールでファイルを送るには、Amazonでの設定が必要になります。
まずは、Amazon上で設定を行います。
Amazonのアカウントサービスからコンテンツの端末と管理を選択します。

00062

「コンテンツと端末の管理」の画面では、Kindleの設定が行えます。
00063

設定のタブの「パーソナル・ドキュメント設定」からKindleへのSend-to-Kindle Eメールアドレスを確認します。
また、「パーソナル・ドキュメントの保存」を有効に変更します。
「承認済みEメールアドレス一覧」に送信元のEメールアドレスを登録します。ここで登録したEメールアドレスからしかKindleへメールを遅れません。


KindleでのHTML

Kindleで使えるHTMLフォーマットは「基本的なHTMLのフォーマットのガイドライン」を参考にしましょう。
ここでは、ニュースの区切れを改ページで区切るため、以下のタグを使用します。このタグはKindle専用の特別なタグになります。

<mbp:pagebreak/>

Pythonプログラムでの実行

プログラムは以下の順で実行します。

0.決まった時間にプログラムを動かす
1.RSSからコンテンツのURLを取得
2.URLを指定して、Webページを取得
3.Webページから、タイトルとニュース内容を抽出
4.抽出した情報からHTMLファイルを作成
5.HTMLファイルを添付してkindleに送信

0.決まった時間にプログラムを動かす
決まった時間にプログラムを動かすのは、cronを使用します。
決まった時間に処理する」のページを参考に、24時間に一回サイトからニュースを取得し、メールに添付して送信します。

1.RSSからコンテンツのURLを取得
RSSを取得する」を参考に、RSSからコンテンツの情報を取得します。

2.URLを指定して、Webページを取得
Webページを取得する」を参考に、URLを指定して、Webページを取得します。

3.Webページから、タイトルとニュース内容を抽出
Web(HTML)から情報を抽出する」を参考に、取得したWebページから情報を抽出します。

4.抽出した情報からHTMLファイルを作成
テンプレートからファイル生成」を参考に、抽出した情報とテンプレートを組み合わせて、HTMLファイルを生成します。

5.HTMLファイルを添付してkindleに送信
Gmailで簡単にメール送信」を参考に、HTMLファイルを添付して、GmailでKindelへ送信します。

上記を含めたサンプルプログラムは以下になります。
サンプルプログラムのkindleアドレスを変更して、Pythonプログラムとして実行するとニュースを取得後、Kindleへ送信されます。JapanToday以外のニュースを取得する場合は、HMTLファイルからの抽出方法を変更する必要があります。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import feedparser
import requests
import lxml.html
import gmail
import re
import os
from time import mktime
from datetime import datetime

#Kindleのアドレス
KINDLE_ADDRESS = "XXXXXXXXXXXXXX@kindle.com"

class News:
    """
    ニュースを格納するクラス
    """
    def __init__(self, title, content, url, date):
        self.title = title
        self.url = url
        self.date = date
        self.content = content
    def showinfo(self):
        print '%s (%s)' % (self.title, self.date)

def create_html(list, filename):
    from jinja2 import Environment, FileSystemLoader
    path = os.path.abspath(os.path.dirname(__file__))
    env = Environment(loader=FileSystemLoader(path, encoding='utf8'))
    tpl = env.get_template('template.html')

    news_list = []
    for news in list:
        content = news.content
        news_list.append({'title':news.title, 'body':content})

    #現在時刻を取得
    now = datetime.today()
    title = now.strftime("News_%Y-%m-%d_%H:%M:%S")

    html = tpl.render({'title':title, 'news_list':news_list})

    tmpfile = open(path + "/" + filename, 'w') #書き込みモードで開く
    tmpfile.write(html.encode('utf-8'))
    tmpfile.close()


if __name__ == '__main__':

    #RSSのURL
    rss_url = "http://www.japantoday.com/feed/"
    #interval_time時間以内のニュースを取得
    interval_time = 24

    #空のNewsリスト
    news_list = []

    #現在時刻を取得
    now = datetime.today()

    feed = feedparser.parse(rss_url)
    for entry in range(len(feed.entries)):

        #RSSの内容を一件づつ処理する
        title = feed.entries[entry].title
        link = feed.entries[entry].link

        #現在時刻から更新日時の時間差を確認
        tmp = feed.entries[entry].updated_parsed
        date = datetime.fromtimestamp(mktime(tmp))
        diff_time = now - date
        diff_hours = (diff_time.seconds/3600) + (diff_time.days*24)

        if diff_hours <= interval_time:
            #interval_time時間以内に更新された記事のみを対象とする

            #Webページ(HTML)の取得
            req = requests.get(link)
            root = lxml.html.fromstring(req.text)

            #HTMLから記事の抽出(Japan Today)
            title = root.get_element_by_id('main_title').text
            content = lxml.html.tostring(root.get_element_by_id('article_content'))
            p = re.compile(r"<[^>]*?>")
            content = p.sub("", content)

            #記事リストの中に追加
            news = News(title, content, link, date)
            news_list.append(news)

    filename = now.strftime("News_%Y-%m-%d_%H:%M:%S") + ".html"

    create_html(news_list, filename)

    #メッセージの作成
    to_addr = KINDLE_ADDRESS
    subject = filename
    body = ""
    mime={'type':'text', 'subtype':'comma-separated-values'}
    attach_file={'name':filename, 'path':filename}
    msg = gmail.create_message(gmail.ADDRESS, to_addr, subject, body, mime, attach_file)

    #メールの送信
    gmail.send(gmail.ADDRESS, [to_addr], msg)

Kindleには以下のテンプレートを適応して、メールに添付しています。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
{% for news in news_list %}

<h1>{{ news.title|safe }}</h1>



        {{ news.body|safe }}
    

    <mbp:pagebreak/>
{% endfor %}
</body>
</html>

プログラムを実行すると、ニュースをKindleに送信します。

00068

Pocket