yu0405jie 发表于 2017-12-26 22:20:09

基于树莓派+Kindle的RSS阅读器

十分感谢e络盟提供的比赛赞助基金。

一、项目名称:
基于树莓派+Kindle的RSS阅读器

1.原理介绍
本系统通过python编程读取rss源中的内容,首先利用正则表达式提取rss源发布时间,并将rss源中的时间与当前时间进行对比,当在一天以内时则认为是最新数据,将其解析完成后转换为html文件,在利用kindle提供的邮箱推送文档的功能,使用python将生成的html的文件以邮件的方式发送至kindle对应的邮箱,完成rss内容的推送。

2.系统版本
RASPBIAN STRETCH LITE
最新版本下载地址
https://downloads.raspberrypi.org/raspbian_lite_latest

3. 应用源代码:
本系统使用python3.5.3进行编程,首先我们需要安装第三方库feedparser,这里直接使用pip进行安装:pip3 install feedparser包安装完成后,就开始了正式的编程之旅了,首先我们要能解析出rss内容并转换为html文件,这里创建一个类RssParser,代码如下# -*- coding:utf-8 -*-

import feedparser
import date_cmp

class RssParser:
    def __init__(self, rss_url):
      self.rss = feedparser.parse(rss_url)

    def get_feed_title(self):
      return self.rss.feed.title

    def get_item_cnt(self):
      return len(self.rss.entries)

    def get_item_date(self, index):
      return self.rss.entries.updated

    def get_item_title(self, index):
      return self.rss.entries.title

    def get_itme_content(self, index):
      return self.rss.entries.summary

    def get_item_url(self, index):
      return self.rss.entries.link

    def generate_html(self):
      html_template = """
      <!DOCTYPE html>
      <html lang="en">
      <head>
            <meta charset="UTF-8">
      </head>
      <body>
            {content}
      </body>
      </html>
      """
      file_name = self.get_feed_title() + '.html'
      html_content = ''
      dateCmp = date_cmp.DateCmp()
      for i in range(self.get_item_cnt()):
            if dateCmp.IsLastest(self.get_item_date(i)):
                item_title = self.get_item_title(i)
                item_content = self.get_itme_content(i)
                item_url = self.get_item_url(i)
                html_content = html_content + '<h2>' + '<a href=\"' + item_url + '\">' + item_title + '</a></h2>\r\n'
                html_content = html_content + '<div class=\"summary\">\r\n' +item_content + '\r\n</div>\r\n'

      if 0 != len(html_content):
            html = html_template.format(content=html_content)
            html = html.encode("utf-8")
            f = open(file_name, 'wb')
            f.write(html)
            f.close()
            return file_name
      else:
            return '\0'

如上面代码所示中,feedparser是我们安装的第三方类,date_cmp是自己编写的用于从字符串中解析出时间并与当前时间进行对比的包,当字符串显示的时间与当前时间在一天以内时,则接口函数IsLastest返回True,否则返回False,其代码如下:# -*- coding:utf-8 -*-
import re
import datetime

class DateCmp:
    def __init__(self):
      self.month_map = {
            'Jan':'01',
            'Feb':'02',
            'Mar':'03',
            'Apr':'04',
            'May':'05',
            'Jun':'06',
            'Jul':'07',
            'Aug':'08',
            'Sep':'09',
            'Oct':'10',
            'Nov':'11',
            'Dec':'12'
      }
      self.date_patton0 = \
            r'(20\d{2})[-/]?((?:?|))[-/]?((?:?|))?'
      self.date_patton1 = \
            r'({3,4}),[ |\t]?((?:?|))[ |\t]?({3,4})[ |\t]?(20\d{2})'
      self.time_patton = \
            r'((?:?|])):((?:?|])):((?:?|]))'

    def Str2Date(self, str):
      year = 0
      month = 0
      day = 0
      hour = 0
      minute = 0
      second = 0

      m = re.findall(self.date_patton0, str)#xxxx-xx-xx xx:xx:xx
      if 0 == len(m):
            m = re.findall(self.date_patton1, str) #aaa, xx aaa xxxx xx:xx:xx
            if 0 == len(m):
                return None
            else:
                year = int(m)
                month = int(self.month_map])
                day = int(m)
      else:
            year = int(m)
            month = int(m)
            day = int(m)

      m = re.findall(self.time_patton, str)
      if 0 != len(m):
            hour = int(m)
            minute = int(m)
            second = int(m)
      else:
            return None

      try:
            b = datetime.datetime(year, month, day, hour, minute, second)
      except ValueError:
            b = None
      return b

    def IsLastest(self, str):
      date_get = self.Str2Date(str)
      if None == date_get:
            return True
      else:
            date_now = datetime.datetime.now()
            date_diff = date_now - date_get
            if date_diff.days < 1:
                return True
            else:
                return False
当html文件可以正常生成了,接下来就是使用邮箱发送文件了,python代码如下所示:# -*- coding:utf-8 -*-
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

class EmailSend:
    def __init__(self):
      self.msg = MIMEMultipart()

    def Login(self, server, user, pwd):
      self.smtp = smtplib.SMTP(server, timeout = 30)
      self.smtp.login(user, pwd)
      self.User = user
      self.Pwd = pwd

    def AddText(self, text):
      part = MIMEText(text)
      self.msg.attach(part)

    def AddAppendix(self, file_name):
      part = MIMEApplication(open(file_name,'rb').read())
      part.add_header('Content-Disposition', 'attachment', filename=file_name)
      self.msg.attach(part)

    def SendEmail(self, to):
      self.msg['Subject'] = 'Convert'
      self.msg['From'] = self.User
      self.msg['To'] = to
      self.smtp.sendmail(self.User, to, self.msg.as_string())
      pass

    def Logout(self):
      self.smtp.close()在上述过程中软件界面如果什么都不显示,会十分单调,这里添加几行python代码,就可以获得树莓派的温度,如下# -*- coding:utf-8 -*-
import os

class RaspberryInfo:
    # Get CPU temperature as a character string
    def GetCpuTemperature(self):
      res = os.popen('vcgencmd measure_temp').readline()
      self.CpuTemperature = res.replace("temp=","").replace("'C\n","")OK,代码都已编写完成了,接下来就是编写一个主程序对上述功能进行调用了,在调用之前,我们先要配置发送邮箱的服务器、用户名和密码、kindle接收邮箱的地址,rss源读取的时间,rss源地址,这些内容分别保存在user_email.txt文件、kindle_email.txt、timer.txt、urls.txt四个文件中,如下所示:
user_email.txt文件smtp.126.com
xxxxxx@126.com
passwordkindle_email.txt文件xxxxxxx@kindle.cn
timer.txt文件13:10
urls.txt文件http://feed.cnblogs.com/blog/sitehome/rss
最后附上主函数实现整个系统的功能# -*- coding:utf-8 -*-

from mail_send import EmailSend
from rss_reader import RssParser
from get_raspberry_info import RaspberryInfo
import time
import datetime
import sys
import os

print('正在启动,请稍后...')
#读取发送邮箱的用户名和密码
f = open('user_email.txt', 'rt')
= f.readlines();
server = server.strip('\n')
user = user.strip('\n')
pwd = pwd.strip('\n')
f.close();

#读取发送的kindle邮箱
f = open('kindle_email.txt', 'rt')
kindle_email = f.readline()
kindle_email = kindle_email.strip('\n')
f.close()

#读取发送时间
f = open('timer.txt', 'rt')
send_time = f.readline()
send_time = send_time.strip('\n')
= send_time.split(':')
send_hour = int(hour)
send_minute = int(minute)
f.close()

#登录邮箱
email_send = EmailSend()
email_send.Login(server,user,pwd);

#获取rss内容并转换成网页
f = open('urls.txt', 'rt')
urls = f.readlines()

#获取当前时间,当到达发送时间时,则读取rss内容,转换为html并发送至kindle邮箱
while True:
    now_time = datetime.datetime.now()
    #达到发送时间
    if now_time.hour == send_hour and now_time.minute == send_minute:
      for url in urls:
            url = url.strip('\n')
            rss = RssParser(url)
            file_name = rss.generate_html()
            if file_name != '\0':
                email_send.AddAppendix(file_name)
                email_send.SendEmail(kindle_email)
                print('send email success                              ')
                time.sleep(90)
               
    else:
      #显示树莓派信息
      rsp_info = RaspberryInfo()
      rsp_info.GetCpuTemperature()
      info = 'CPU 温度:' + rsp_info.CpuTemperature
      time_info = '    当前时间:%d:%d:%d \r ' % (now_time.hour, now_time.minute, now_time.second)

      sys.stdout.writelines('                                             \r')
      sys.stdout.writelines(info + time_info)
      time.sleep(1)

4. 硬件连线图
本系统只需要一块树莓派即可,真的要连的话就用网线把树莓派和路由器连起来好了!:lol

5. 演示视频
由于从采集完成到发送邮件到kindle接收,是一段比较长的时间,且中间过程没有任何可以演示的地方,因此这里就发几张截图好了,一样可以看出效果哦。
图一:等待过程中,显示树莓派CPU温度和当前的时间

图二:为了防止作假,我们先看看kindle里面可是只有几本电子书哦

图三:rss获取时间到了,邮件发送完成后会有一条提示信息:send email success

图四:kindle已经收到推送了,好开心!

图五:迫不及待的打开看看里面的内容

图六:唯一不太方便的就是,rss源里的内容只是一些概要,要想看详细内容,需要理由kindle的浏览器

stary666 发表于 2018-1-30 06:55:02

看看了,,,

dem0 发表于 2018-1-26 13:31:21

请问笔记本事怎么用作树莓派显示器的?

yu0405jie 发表于 2018-1-3 09:37:53

ky123 发表于 2018-1-2 08:56 static/image/common/back.gif
《飘》看不看呀,估计你不喜欢呢。可以看看《教父》,大学有一段时间特别迷民国人物传记,你也可以试试。 ...

恩恩,好的,谢谢啦

ky123 发表于 2018-1-2 08:56:58

yu0405jie 发表于 2018-1-2 08:49 static/image/common/back.gif
那么巧啊,你有什么好看的书推荐一下呗

《飘》看不看呀,估计你不喜欢呢。可以看看《教父》,大学有一段时间特别迷民国人物传记,你也可以试试。书籍推荐类有一个微信公众号warfalcon,然后学习方法类有一个公众号白诗诗。

yu0405jie 发表于 2018-1-2 08:49:23

ky123 发表于 2017-12-27 09:23 static/image/common/back.gif
我的kindle也是这款滴♬︎*(๑ºั╰︎╯︎ºั๑)♡︎

那么巧啊,你有什么好看的书推荐一下呗

ky123 发表于 2017-12-27 09:23:31

我的kindle也是这款滴♬︎*(๑ºั╰︎╯︎ºั๑)♡︎
页: [1]
查看完整版本: 基于树莓派+Kindle的RSS阅读器

Baidu
map