使用kindlegen实现自主文件发送
最近入手一部kindle,本着努力学习的想法,想通过它来提高自己的英文阅读水平,不过,入手之后,发现用来看杂文的时间远大于看英文文章的时间,时间罪过,为了减轻自己的负罪感,决定要用它来实现最初的作用, 用来阅读一些文献,可是放眼望去,现在网上大部分的kindle推送功能一般不会有这方面的内容,大部分的是为了吸引读者,放一些网络小说上来,最可恶的还有的要收费,按月付,按周付各种付费方法,只有你想不到,没有他想不到的,于是想自己做一个推送,毕竟这年头流行私人定制吗。
说干就干,首先要理清一下思路,第一,我需要了解推送的原理,第二,我需要构建推送的文章。好了,先来解决第一部:推送原理
经百度大叔的指导发现:每部kindle都有一个自己的@kindle.com的邮箱,这个一般放在【设置】-【全部设置】-【我的账户】-【发送至Kindle】电子邮件地址,我的是paperwhite,是在这个位置,可能其他型号的不住这位置,不过应该很好找,好了,这个邮箱就是用来当作被发送的邮箱,就是说你只要往这个邮箱里面发生kindle可以识别格式的文件,那么他就会下载到你的kindle里面,但是不可能什么人都可以发送对吧,不然你的kindle会变成垃圾箱,因此首先要登录亚马逊邮箱,打开【我的账户】列表里面【管理我的设备和内容】,选择【设置】,找到如【以认可的发件人邮箱地址】,添加即可如同
所以这第一步就算完成一半了,为什么是一半,因为要编程自主实现啊!
好了,第二个问题,构建推送的文章,这是我需要的文章地址:http://www.tandfonline.com/toc/ilab20/54/3?nav=tocList,我需要最新的文章,那么简单的说,就是每次有最新的文章我都要会自动发送到我的kindle,但是这个杂志两个月才发一次刊,所以基本上我可以手动来操作,没必要再去自动实现。因此我准备只写一个小工具来抓取这个内容,融合可以自动发送到kindle邮箱。
要想实现自动抓取,也就是爬虫,我选择比较熟悉的selenium+phantomJS框架来实现,其实一开始我使用的pyqt5.qtwebKitengine来实现,可是速度太慢,特别着急,所以就改用这个组合。phantomjs是一个无界面浏览器,selenium是一个自动化测试框架,基于python实现的。好了,直接上代码,简简单单几行就搞定:
首先建立虚拟环境,然后在虚拟环境里面操作,导入webdriver和etree两个子模块
通过webdriver.PhantomJS()来建立浏览器驱动,也可以利用本机电脑上的火狐和谷歌浏览器,形如webdriver.Chrome()或者webdriver.Firefox()
接着通过get方法来连接目标网址,通pageg_source属性来获取整个html代码,这个方法比较适合动态网页的获取,一些常用ajax方法处理的动态网页很难获取实际的标签里面的内容,但是通过这种加载到浏览器引擎里面之后就可以全部实现ajax代码的完全运行。不过要提的是这个属于国外网站,国外网站的访问速度,四个字苦不堪言,呜呜
接下来就是解析里面我要的内容:
通过lxml模块来解析成树模型,然后通过xpath来解析:
如图,解析出了文献的题目和相对地址,然后接着做成绝对地址访问截取其中的文献内容就行。
那么解析出来的文章怎么做成kindlegen识别的格式mobi格式呢
这是网上的图片,说的是mobi格式包含的文件,其实还可以有自定义的css,kindlegen这个工具是亚马逊推出的命令行生成mobi工具,目标文件为opf文件,加入手上有paper.html,paper.opf,toc.html,toc.ncx,另外附加图片,css等文件,只要执行kindlegen paper.opf就可以生成mobi文件,因此我们需要构建paper.html,paper.opf,toc.html,toc.ncx文件,这里大家请参考:http://www.cnblogs.com/buptzym/p/5249662.html这篇文章,我同样选用的是jinja2模块,如果没有安装,可以通过pip install jinja2安装,因为我之前一直在看flaskweb编程,flask使用的就是jinja2模块,所以有些选用这个模块
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="BookId">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
<dc:title>{{ title }}</dc:title>
<dc:language>en-us</dc:language>
</metadata>
<manifest>
<!-- table of contents [mandatory] -->
<item id="toc" media-type="application/x-dtbncx+xml" href="toc.ncx"/>
<item id="tochtml" media-type="application/xhtml+xml" href="toc.html"/>
{% for item in navigation %}
<item id="{{ item.id }}" media-type="application/xhtml+xml" href="{{ item.href }}"/>
{% endfor %}
{% for item in media %}
<item id="{{ item.id }}" media-type="image/{{ item.format}}" href="{{ item.href}}"/>
{% endfor %} </manifest>
<spine toc="{{ title }}">
<!-- the spine defines the linear reading order of the book -->
<itemref idref="toc"/>
<itemref idref="tochtml"/>
{% for item in navigation %}
<itemref idref="{{ item.id }}"/>
{% endfor %}
</spine>
<guide>
<reference type="toc" title="Table of Contents" href="toc.html"></reference>
<reference type="text" title="Welcome" href="toc.html"></reference>
</guide>
</package>
这里我直接复制的上述网址大神的代码,因为我只要把item这个变量变成paper就可以了,所以对于我来说,这个代码可以直接拿来用.
那现在只要写个bat文件将"kindlegen.exe paper.opf"写入进去,前提,kindlegen直接写路径或者设置环境变量就可以生成目标mobi文件
那么文件生成了,怎样将其发送到指定的邮箱呢:我选用smtplib模块,先构建一个smtp类,再传入paper参数,如图
import smtplib
import email.MIMEMultipart
import email.MIMEText
import email.MIMEBase
from email.utils import parseaddr, formataddr
import os.path class smtp:
def __init__(self,paper):
self.paper=paper
self.From='你的邮箱'
self.To='你的kindle邮箱'
self.server = smtplib.SMTP("smtp.126.com") def mimneMultipart(self): # 构造MIMEMultipart对象做为根容器
main_msg = email.MIMEMultipart.MIMEMultipart() # 构造MIMEText对象做为邮件显示内容并附加到根容器
text_msg = email.MIMEText.MIMEText("kindle sendding machine")
main_msg.attach(text_msg) # 构造MIMEBase对象做为文件附件内容并附加到根容器
contype = 'application/octet-stream'
maintype, subtype = contype.split('/', 1) ## 读入文件内容并格式化
data = open(self.paper, 'rb')
file_msg = email.MIMEBase.MIMEBase(maintype, subtype)
file_msg.set_payload(data.read( ))
data.close( )
email.Encoders.encode_base64(file_msg) ## 设置附件头
basename = os.path.basename(file_name)
file_msg.add_header('Content-Disposition','attachment', filename = basename)
main_msg.attach(file_msg) # 设置根容器属性
main_msg['From'] = self.From
main_msg['To'] = self.To
main_msg['Subject'] = "convert"
main_msg['Date'] = email.Utils.formatdate( ) # 得到格式化后的完整文本
fullText = main_msg.as_string( ) # 用smtp发送邮件
try:
self.server.sendmail(self.From, self.To, fullText)
finally:
self.server.quit()
这样就基本实现自己的kindle文章的定制,以上代码参考了大量网上大神的,因为我不喜欢重复造轮子,嘿嘿!
使用kindlegen实现自主文件发送的更多相关文章
- Redis学习笔记~conf自主集群模式
回到目录 Redis自主提供了集群模式,当然也只是比较简单的读写分离模式,或者叫主从模式,它在各个redis服务端自己做数据同步机制,当然就是将主服务端的信息同步到各个slave服务器上,在客户端集成 ...
- WebApi系列~自主宿主HttpSelfHost的实现
回到目录 宿主一词我们不会陌生,它可以看作是一个基础设施,它为一些服务和功能提供最底层的支持,如你的web应用程序可以运行在iis或者apache上,而这两个东西就是web应用程序的宿主,而今天说的自 ...
- 极客DIY:制作一个可以面部、自主规划路径及语音识别的无人机
引言 现在大部分无人机厂商都会为第三方开发者提供无人机API接口,让他们更容易地开发无人机飞行控制应用程序,让无人机想怎么玩就怎么玩.有的API接口可以帮助开发者开发基于Web版的APP.手机APP甚 ...
- 热烈庆祝华清远见成功自主研发Farsight TV 智能机顶盒
近日,华清远见研发中心再传喜讯:Farsight TV 智能机顶盒研发成功并投入教学!这是华清远见研发中心继开源平板电脑.智能医疗终端.智能家居终端后独立成功研发的又一智能硬件!至此,开创了华清远见自 ...
- Windows 系统下json 格式的日志文件发送到elasticsearch
Windows 系统下json 格式的日志文件发送到elasticsearch配置 Nxlog-->logstash-->ElasticSearch Logstash https://ww ...
- 再谈自主开发与企业IT管理
前两天写<自主开发与带兵打仗>分析了一下自主开发的利与弊,得到了园内不少朋友的反馈,但我觉得还有很多东西没有交待清楚,可能有很多朋友也跟我一样在公司的IT部门,有自己的研发团队也有很多外购 ...
- 《黄聪:手机移动站SEO优化教程》4、如何实现手机移动网站和PC站点的自主适配
视频地址:http://www.tudou.com/programs/view/v4Hur5vjav4/ 1.自主适配 A:站点自己做好PC与手机之间的适配,以及手机站各个版式之间的适配.当手机用户通 ...
- asp天猫自主发码的请求
这几天在做天猫自主发码.实现了通知和核销部门.其他的部分待后续实现. 值得注意的是consume回调中,要加入sign_method=md5
- 揭秘淘宝自主研发的文件系统:TFS
目前,国内自主研发的文件系统可谓凤毛麟角.淘宝在这一领域做了有效的探索和实践,Taobao File System(TFS)作为淘宝内部使用的分布式文件系统,针对海量小文件的随机读写访问性能做了特殊优 ...
随机推荐
- 添加Metasploit-payload到已有的Android项目中
metasploit在写这篇文章之前,笔者可以说是对java一窍不通,也从来没有写过什么Android应用,在几天的摸爬滚打中终于实现了最终的目的,就是在已有Apk源码的情况下,用了比较另类的方式,添 ...
- 微信小程序开发之获取openid及用户信息
1. 获取openid 1.1 获取code 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的会话密钥(session_key).用户数据的加解 ...
- 利用JavaScript数组动态写入HTML数据节点
如果想要使用数组来写入HTML数据,绝对需要的是一个Key值,由Key来引导遍历数组各项:此外,使用DOM原生方法写入文档,用同一个CSS样式渲染它们,这样可以极大地减少开发时间和减少维护成本,此方法 ...
- cassandra.yaml 配置 (非原创,侵删)
Copy from: http://blog.csdn.net/y_h_t/article/details/11917531 Cassandra中所有的运行配置都是在配置文件cassandra.yam ...
- cocoapods卸载重装 解决clone,install,search很慢的问题
电脑上面的cocoapods clone,pod install search的时候非常非常的慢,尝试了很多方法都无法解决,最后只能尝试着重装看看能不能解决问题 卸载 sudo gem uninsta ...
- BattleInfo
private Dictionary<string, UILabel> mLabels; private Dictionary<string,UISprite> mSprite ...
- Quartz.net 定时任务之Cron表达式
一.cron表达式简单介绍和下载 1.在上一篇博客"Quartz.net 定时任务之简单任务"中,我简单介绍了quartz的使用,而这篇博客我将介绍cron的具体使用(不足之处望大 ...
- JS 浏览器cookie的设置,读取,删除
JavaScript是运行在客户端的脚本,因此一般是不能够设置Session的,因为Session是运行在服务器端的. 而cookie是运行在客户端的,所以可以用JS来设置cookie. 假设有这样一 ...
- 【面向对象设计原则】之依赖倒置原则(DIP)
依赖倒转原则(Dependency Inversion Principle, DIP):抽象不应该依赖于细节,细节应当依赖于抽象.换言之,要针对抽象(接口)编程,而不是针对实现细节编程. 开闭原则( ...
- 初码-Azure系列-记一次MySQL数据库向Azure的迁移
初码Azure系列文章目录 还在继续给客户迁移不同的系统到Azure,这一次是一个系统的MySQL数据库要迁移,将迁移过程记录一下 原系统环境 数据库版本:MySQL Community Editio ...