1赞

6回答

2收藏

[大赛作品提交] 基于树莓派+Kindle的RSS阅读器

Raspberry Pi Raspberry Pi 9697 人阅读 | 6 人回复 | 2017-12-26

十分感谢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进行安装:
  1. pip3 install feedparser
复制代码
包安装完成后,就开始了正式的编程之旅了,首先我们要能解析出rss内容并转换为html文件,这里创建一个类RssParser,代码如下
  1. # -*- coding:utf-8 -*-

  2. import feedparser
  3. import date_cmp

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

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

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

  11.     def get_item_date(self, index):
  12.         return self.rss.entries[index].updated

  13.     def get_item_title(self, index):
  14.         return self.rss.entries[index].title

  15.     def get_itme_content(self, index):
  16.         return self.rss.entries[index].summary

  17.     def get_item_url(self, index):
  18.         return self.rss.entries[index].link

  19.     def generate_html(self):
  20.         html_template = """
  21.         <!DOCTYPE html>
  22.         <html lang="en">
  23.         <head>
  24.             <meta charset="UTF-8">
  25.         </head>
  26.         <body>
  27.             {content}
  28.         </body>
  29.         </html>
  30.         """
  31.         file_name = self.get_feed_title() + '.html'
  32.         html_content = ''
  33.         dateCmp = date_cmp.DateCmp()
  34.         for i in range(self.get_item_cnt()):
  35.             if dateCmp.IsLastest(self.get_item_date(i)):
  36.                 item_title = self.get_item_title(i)
  37.                 item_content = self.get_itme_content(i)
  38.                 item_url = self.get_item_url(i)
  39.                 html_content = html_content + '<h2>' + '<a href="' + item_url + '">' + item_title + '</a></h2>\r\n'
  40.                 html_content = html_content + '<div class="summary">\r\n' +  item_content + '\r\n</div>\r\n'

  41.         if 0 != len(html_content):
  42.             html = html_template.format(content=html_content)
  43.             html = html.encode("utf-8")
  44.             f = open(file_name, 'wb')
  45.             f.write(html)
  46.             f.close()
  47.             return file_name
  48.         else:
  49.             return '\0'

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

  4. class DateCmp:
  5.     def __init__(self):
  6.         self.month_map = {
  7.             'Jan':'01',
  8.             'Feb':'02',
  9.             'Mar':'03',
  10.             'Apr':'04',
  11.             'May':'05',
  12.             'Jun':'06',
  13.             'Jul':'07',
  14.             'Aug':'08',
  15.             'Sep':'09',
  16.             'Oct':'10',
  17.             'Nov':'11',
  18.             'Dec':'12'
  19.         }
  20.         self.date_patton0 = \
  21.             r'(20\d{2})[-/]?((?:[0-9]?|[1-9])[0-9])[-/]?((?:[0-9]?|[1-9])[0-9])?'
  22.         self.date_patton1 = \
  23.             r'([A-Za-z]{3,4}),[ |\t]?((?:[0-9]?|[1-9])[0-9])[ |\t]?([A-Za-z]{3,4})[ |\t]?(20\d{2})'
  24.         self.time_patton = \
  25.             r'((?:[0-9]?|[1-9]])[0-9]):((?:[0-9]?|[1-9]])[0-9]):((?:[0-9]?|[1-9]])[0-9])'

  26.     def Str2Date(self, str):
  27.         year = 0
  28.         month = 0
  29.         day = 0
  30.         hour = 0
  31.         minute = 0
  32.         second = 0

  33.         m = re.findall(self.date_patton0, str)  #xxxx-xx-xx xx:xx:xx
  34.         if 0 == len(m):
  35.             m = re.findall(self.date_patton1, str) #aaa, xx aaa xxxx xx:xx:xx
  36.             if 0 == len(m):
  37.                 return None
  38.             else:
  39.                 year = int(m[0][3])
  40.                 month = int(self.month_map[m[0][2]])
  41.                 day = int(m[0][1])
  42.         else:
  43.             year = int(m[0][0])
  44.             month = int(m[0][1])
  45.             day = int(m[0][2])

  46.         m = re.findall(self.time_patton, str)
  47.         if 0 != len(m):
  48.             hour = int(m[0][0])
  49.             minute = int(m[0][1])
  50.             second = int(m[0][2])
  51.         else:
  52.             return None

  53.         try:
  54.             b = datetime.datetime(year, month, day, hour, minute, second)
  55.         except ValueError:
  56.             b = None
  57.         return b

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

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

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

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

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

  21.     def SendEmail(self, to):
  22.         self.msg['Subject'] = 'Convert'
  23.         self.msg['From'] = self.User
  24.         self.msg['To'] = to
  25.         self.smtp.sendmail(self.User, to, self.msg.as_string())
  26.         pass

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

  3. class RaspberryInfo:
  4.     # Get CPU temperature as a character string
  5.     def GetCpuTemperature(self):
  6.         res = os.popen('vcgencmd measure_temp').readline()
  7.         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文件
  1. smtp.126.com
  2. xxxxxx@126.com
  3. password
复制代码
kindle_email.txt文件
  1. xxxxxxx@kindle.cn
复制代码
timer.txt文件
  1. 13:10
复制代码
urls.txt文件
  1. http://feed.cnblogs.com/blog/sitehome/rss
复制代码
最后附上主函数实现整个系统的功能
  1. # -*- coding:utf-8 -*-

  2. from mail_send import EmailSend
  3. from rss_reader import RssParser
  4. from get_raspberry_info import RaspberryInfo
  5. import time
  6. import datetime
  7. import sys
  8. import os

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

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

  22. #读取发送时间
  23. f = open('timer.txt', 'rt')
  24. send_time = f.readline()
  25. send_time = send_time.strip('\n')
  26. [hour, minute] = send_time.split(':')
  27. send_hour = int(hour)
  28. send_minute = int(minute)
  29. f.close()

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

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

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

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

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

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

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

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

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

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

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

关注下面的标签,发现更多相似文章
分享到:
回复

使用道具 举报

回答|共 6 个

倒序浏览

沙发

ky123

发表于 2017-12-27 09:23:31 | 只看该作者

我的kindle也是这款滴??*(???╰?╯????)??
板凳

yu0405jie

发表于 2018-1-2 08:49:23 | 只看该作者

ky123 发表于 2017-12-27 09:23
我的kindle也是这款滴??*(???╰?╯????)??

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

ky123

发表于 2018-1-2 08:56:58 | 只看该作者

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

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

yu0405jie

发表于 2018-1-3 09:37:53 | 只看该作者

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

恩恩,好的,谢谢啦
6#

dem0

发表于 2018-1-26 13:31:21 | 只看该作者

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

stary666

发表于 2018-1-30 06:55:02 | 只看该作者

看看了,,,
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条