美文网首页程序员
nodejs 爬虫 - 电子书应用与一键自动推送到 Kindl

nodejs 爬虫 - 电子书应用与一键自动推送到 Kindl

作者: 小丶王子 | 来源:发表于2018-07-17 16:12 被阅读0次

    由于闲暇时间会看电子书小说,一时心血来潮,想搞个电子书爬虫,于是阅读了下 nodejs 官网文档,并未深究,做了个电子书爬虫与 kindle 自动推送的网站,供自己使用

    写这篇文章就是想记录下自己是怎么一步一步完善这个网站功能的,使用到的技术很普通:nodejs、jq,做的也很粗糙,够自己使用,网址:http://book.ln26.net,效果如下

    登录页
    搜索页
    • 实现思路

    _思路是挺重要的,做程序就是这样,我也是一时心血来潮,所以在开始这个项目前,我也是完全没有 nodejs 的开发经验的,但是 js 的一些基础还是要有的

    核心思路:

    1、html 提供书名输入
    2、nodejs 搭建服务器,根据书名去电子书网站爬取内容
    3、把关键下载地址爬下来,供下载与 kindle 推送
    4、实现下载文件
    5、实现压缩包的文件解压(部分电子书网站提供 zip 的下载)
    6、实现邮件发送(因为 kindle 的推送基于邮件发送)
    7、删除下载的文件

    整体说来就是利用 nodejs 服务,把电子书下载下来,zip 的包就解压缩,拿到里面的 电子书.txt,然后自动发送邮件带上电子书.txt 的附件,发送到 kindle 绑定的邮箱 ,下面介绍我是怎么一步步完成的

    • 一步步完成

    1、html 的输入部分,没有什么特别的,使用 jq 获取表单上的用户输入,然后把搜索的关键字传给 nodejs 服务搭建的接口上
    2、nodejs 搭建服务器,这一步开始,就是我自己的探索过程:

    在nodejs官网上下载好node,安装好最新版本,轻轻松松,然后开始搭建第一个应用,在网上搜索了一番,推荐使用 Express,于是又跑到 Express,看了下入门和创建应用服务

    $ npm install express --save  // 安装好 express
    

    创建一个简单的应用 test-node.js

    var express = require('express');
    var app = express();
    
    // respond with "hello world" when a GET request is made to the homepage
    app.get('/', function(req, res) {
      res.send('hello world');
    });
    app.listen(8888);
    

    在 test-node.js 的目录下执行

    node test-node.js // 启动
    

    在浏览器上打开 http://localhost:8888 能看到 hello world 就说明启动成功了,依旧是轻轻松松,跟着文档走
    接下来就是爬虫的编写了,网上看了下别人的简单例子,推荐使用 superagent,于是就看了下 superagent 的使用

    $ npm install superagent --save  // 安装好 superagent
    
    var superagent = require('superagent');
    var url = 'http://zhannei.baidu.com/cse/search?searchtype=complex&q=123&s=18140131260432570322'; // 一个接受 get 请求的电子书网站
    // 一个简单的 get 请求
    superagent.get(url)
        .end(function (err, res) {
          // 常规的错误处理
          if (err) {
            console.log(err);
          }
          // 网页的抓取内容都在 resr 的 body 里面
          console.log(res);
        });
    
    // 一个简单的 post 请求
    superagent
            .post(url)
            .type('form') // 参数转化为 form data 的格式
            .send({key: 123}) // 参数
            .end(function(err, res) {
                // 常规的错误处理
                if (err) {
                    console.log(err);
                }
                console.log(res);
            })
    

    上面的例子都是我用到的简单的请求,我这里只讲我自己的做法,比较简单粗糙,想了解具体可以去看看相关文档

    3、把关键下载地址爬下来,供下载与 kindle 推送

    因为我是需要去爬相应的电子书,所以我的做法是在网上随便找个电子书网站,在上面找到搜索电子书的地方,随便输入然后点击搜索,就会跳转到相应的搜索页,打开调试面板找到这个页面的数据来源,用 superagent 模拟搜索页的请求,就能获取相应的页面内容了

    拿到页面请求之后的处理

    网上看到部分是在 nodejs 里处理,由于我是个人网站,不想增加服务器压力,就放到了客户端处理,简单来说:我把拿到的数据,返回到客户端,用 jq 提取中间的下载地址,但是电子书网站都会放广告,需要一直往里跳转,才能找到 电子书.txt 的下载地址,所以我做了一个递归查询,从找到的第一个下载地址一直往里爬,直到找到真正的下载地址为止。
    甚至更简单的做法:
    针对某个电子书网站进行爬取,这样就知道往里跳几次就能拿到真正的 电子书.txt 的地址,用 superagent 往里多搜索几次直到拿到 电子书.txt 的地址,用 jq 把 <a> 标签都取出来,塞到自己html 里,这样就能做到点击下载

    4、实现下载文件

    拿到下载地址就 OK 了,利用下载地址把文件下载下来,又一顿百度大法,推荐 fs 文件操作模块,安装 fs 模块 与 request 模块

    $ npm install fs --save
    $ npm install request --save
    

    文件下载操作

    var fs = require('fs');
    var request = require('request');
    
    let name = Date.now() + '.txt'; // 自定义文件名称
    let file = __dirname + '/' + name; // 文件绝对地址
    let stream = fs.createWriteStream(file); // 创建文件
    let url = 'https://dt.80txt.com/1567/无敌黑枪.txt'; // 电子书的下载地址
    
    // 把电子书下载下来,写入到创建的文件
    request(url).pipe(stream).on("close", function (err) {
        console.log('下载成功');
    });
    

    在目录下能看到一个 .txt 文件就说明下载成功啦

    5、实现压缩包的文件解压

    上面例子用到的下载文件是 txt ,但是一般的电子书网站都会提供 zip 的压缩包下载,所以还需要解压缩。还是百度大法,推荐了 adm-zip

    $ npm install adm-zip --save
    

    安装好之后

    var adm_zip = require('adm-zip');
    var fs = require('fs');
    var url = __dirname + '/123.zip'; // 当前目录下的 123.zip 文件
    var name = Date.now() + '.txt';  // 解压后的文件名称
    var unzip = new adm_zip(url);  // 解压
    var files = unzip.getEntries()[0].entryName; // 获取到压缩包里的文件名称
    unzip.extractAllTo(__dirname); // 解压到当前目录
    // 重命名压缩包里面的文件
    fs.rename(__dirname + '/' +files, __dirname + '/' + name, 
        function(err){
                if(err){
                    console.log("重命名失败");
                }else{
                    console.log("解压成功");
                    
                    // 解压成功后删除压缩包
                    fs.unlink(url, function (err) {
                        if(err) throw err;
                        console.log(url + '删除成功')
                    });
                }
            });
    
    6、实现邮件发送

    还是通过网上搜索,推荐使用 nodemailer 模块

    npm install nodemailer --save
    
    npm install nodemailer-smtp-transport --save
    

    直接上代码

    var fs = require('fs');
    var nodemailer = require('nodemailer');
    var smtpTransport = require('nodemailer-smtp-transport');
    
    // 邮箱
    var email = {
        service: '163',
        user: '136xxxxxxxx@163.com',
        pass: 'xxxxx', // 授权码
    };
    var config = {
        email
    };
    
    smtpTransport = nodemailer.createTransport(smtpTransport({
        service: config.email.service,
        auth: {
            user: config.email.user,
            pass: config.email.pass
        }
    }));
    
    // 发送邮件
    var file = './123.txt';  // 下载下来的 txt 文件的地址
    smtpTransport.sendMail({
    
                from: config.email.user,
                to: 'xxx@kindle.cn',
                subject: '123.txt',
                html: '123.txt',
                attachments:[
                    {
                        filename : '123.txt',
                        path: file  // 下载下来的 txt 文件的地址
                    }
                ]
    
            }, function (error, response) {
                if (error) {
                    console.log('error', error);
                }
                // 发送后后删除 txt
                fs.unlink(file, function (err) {
                    if(err) throw err;
                    console.log(file + '删除成功')
                });
                console.log('success');
            });
    

    发送邮件的代码不是很复杂,但是这里有几个点,必须要 注意:
    1、邮件名称、邮件内容、附件名称、附件地址里面的文件名称,最好一致,这里有一个坑,如果不一致,kindle 那边有时会说附件出问题
    2、里面我用的163邮箱,至于里面怎么设置,去网上查下『163邮箱如何开启 SMTP 服务』就好
    3、163邮箱 常规设置 写信设置 附件上传方式 设置为标准模式
    4、要让 kindle 的信任邮箱里,添加你用于推送附件的163邮箱

    注:这里我使用的163邮箱,你们可以随意

    7、删除下载的文件

    上面的代码里已经提到了

    var fs = require('fs');
    var file = './123.txt';  // 文件地址 
    fs.unlink(file, function (err) {
                    if(err) throw err;
                    console.log(file + '删除成功')
                });
    

    值得一提的是, 我上面的所有文件操作的地址,都是使用的绝对地址,用 __dirname + {文件当前地址} 获得绝对地址,这样做的初衷是担心放到服务器上会有问题


    上面的代码我都单独跑过,没有问题,具体的代码实现细节我没有给出来,希望能大家参考这个思路,把里面的关键功能点都实现,然后串起来,做出自己的东西。

    欢迎留言~

    相关文章

      网友评论

        本文标题:nodejs 爬虫 - 电子书应用与一键自动推送到 Kindl

        本文链接:https://www.haomeiwen.com/subject/owewpftx.html