最近入手一部 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 模块,所以有些选用这个模块
- "http://www.idpf.org/2007/opf"version="2.0"unique-identifier="BookId">"http://purl.org/dc/elements/1.1/"xmlns:opf="http://www.idpf.org/2007/opf">
- {{ title }}
- en-us
- "toc"media-type="application/x-dtbncx+xml"href="toc.ncx"/>"tochtml"media-type="application/xhtml+xml"href="toc.html"/>
- {%foriteminnavigation %}
- "{{ item.id }}"media-type="application/xhtml+xml"href="{{ item.href }}"/>
- {% endfor %}
- {%foriteminmedia %}
- "{{ item.id }}"media-type="image/{{ item.format}}"href="{{ item.href}}"/>
- {% endfor %}
- "{{ title }}">"toc"/>"tochtml"/>
- {%foriteminnavigation %}
- "{{ item.id }}"/>
- {% endfor %}
- "toc"title="Table of Contents"href="toc.html">"text"title="Welcome"href="toc.html">
这里我直接复制的上述网址大神的代码,因为我只要把 item 这个变量变成 paper 就可以了,所以对于我来说,这个代码可以直接拿来用.
那现在只要写个 bat 文件将 "kindlegen.exe paper.opf" 写入进去,前提,kindlegen 直接写路径或者设置环境变量就可以生成目标 mobi 文件
那么文件生成了,怎样将其发送到指定的邮箱呢:我选用 smtplib 模块,先构建一个 smtp 类,再传入 paper 参数,如图
- import smtplib
- import email.MIMEMultipart
- import email.MIMEText
- import email.MIMEBase
- fromemail.utilsimport 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 文章的定制,以上代码参考了大量网上大神的,因为我不喜欢重复造轮子,嘿嘿!
来源: http://www.cnblogs.com/missed-forest/p/7096020.html