首页 > 代码库 > 使用kindlegen实现自主文件发送

使用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=http://www.mamicode.com/"toc.ncx"/>
    <item id="tochtml" media-type="application/xhtml+xml" href=http://www.mamicode.com/"toc.html"/>
{% for item in navigation %}
    <item id="{{ item.id }}" media-type="application/xhtml+xml" href=http://www.mamicode.com/"{{ item.href }}"/>
{% endfor %}
 {% for item in media %}
   <item id="{{ item.id }}" media-type="image/{{ item.format}}" href=http://www.mamicode.com/"{{ 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=http://www.mamicode.com/"toc.html"></reference>
    <reference type="text" title="Welcome" href=http://www.mamicode.com/"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 = http://www.mamicode.com/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实现自主文件发送