专栏首页西安-晁州nodejs的简单爬虫

nodejs的简单爬虫

使用nodejs爬虫豆瓣电影数据,要爬取的页面地址:https://movie.douban.com/top250,简单实现如下:

'use strict';

// 引入模块
var https = require('https');
var fs = require('fs');
var path = require('path');
var cheerio = require('cheerio');

// 爬虫的URL信息
var opt = {
    hostname: 'movie.douban.com',
    path: '/top250',
    port: 443
};

// 创建http get请求
https.get(opt, function(res) {
    var html = ''; // 保存抓取到的HTML源码
    var movies = [];  // 保存解析HTML后的数据,即我们需要的电影信息

    // 前面说过
    // res 是 Class: http.IncomingMessage 的一个实例
    // 而 http.IncomingMessage 实现了 stream.Readable 接口
    // 所以 http.IncomingMessage 也有 stream.Readable 的事件和方法
    // 比如 Event: 'data', Event: 'end', readable.setEncoding() 等

    // 设置编码
    res.setEncoding('utf-8');

    // 抓取页面内容
    res.on('data', function(chunk) {
        html += chunk;
    });

    res.on('end', function() {
        // 使用 cheerio 加载抓取到的HTML代码
        // 然后就可以使用 jQuery 的方法了
        // 比如获取某个class:$('.className')
        // 这样就能获取所有这个class包含的内容
        var $ = cheerio.load(html);

        // 解析页面
        // 每个电影都在 item class 中
        $('.item').each(function() {
            // 获取图片链接
            var movie = {
                title: $('.title', this).text(), // 获取电影名称
                star: $('.info .star em', this).text(), // 获取电影评分
                link: $('a', this).attr('href'), // 获取电影详情页链接
                picUrl: $('.pic img', this).attr('src') // 获取电影图片链接
            };

            // 把所有电影放在一个数组里面
            movies.push(movie);
            // 下载图片
            downloadImg('img/', movie.picUrl);
        });

        // 保存抓取到的电影数据
        saveData('data/data.json', movies);
    });
}).on('error', function(err) {
    console.log(err);
});


/**
 * 保存数据到本地
 *
 * @param {string} path 保存数据的文件
 * @param {array} movies 电影信息数组
 */
function saveData(path, movies) {
    // 调用 fs.writeFile 方法保存数据到本地
    fs.writeFile(path, JSON.stringify(movies, null, 4), function(err) {
        if (err) {
            return console.log(err);
        }
        console.log('Data saved');
    });
}

/**
 * 下载图片
 *
 * @param {string} imgDir 存放图片的文件夹
 * @param {string} url 图片的URL地址
 */
function downloadImg(imgDir, url) {
    https.get(url, function(res) {
        var data = '';

        res.setEncoding('binary');

        res.on('data', function(chunk) {
            data += chunk;
        });

        res.on('end', function() {
            // 调用 fs.writeFile 方法保存图片到本地
            fs.writeFile(imgDir + path.basename(url), data, 'binary', function(err) {
                if (err) {
                    return console.log(err);
                }
                console.log('Image downloaded: ', path.basename(url));
            });
        });
    }).on('error', function(err) {
        console.log(err);
    });
}

使用eventproxy版:

var eventproxy = require('eventproxy');
var superagent = require('superagent');
var cheerio = require('cheerio');
var url = require('url');

var cnodeUrl = 'https://cnodejs.org/';

superagent.get(cnodeUrl)
  .end(function (err, res) {
    if (err) {
      return console.error(err);
    }
    var topicUrls = [];
    var $ = cheerio.load(res.text);
    $('#topic_list .topic_title').each(function (idx, element) {
      var $element = $(element);
      var href = url.resolve(cnodeUrl, $element.attr('href'));
      topicUrls.push(href);
    });

    var ep = new eventproxy();

    ep.after('topic_html', topicUrls.length, function (topics) {
      topics = topics.map(function (topicPair) {
        var topicUrl = topicPair[0];
        var topicHtml = topicPair[1];
        var $ = cheerio.load(topicHtml);
        return ({
          title: $('.topic_full_title').text().trim(),
          href: topicUrl,
          comment1: $('.reply_content').eq(0).text().trim(),
        });
      });

      console.log('final:');
      console.log(topics);
    });

    topicUrls.forEach(function (topicUrl) {
      superagent.get(topicUrl)
        .end(function (err, res) {
          console.log('fetch ' + topicUrl + ' successful');
          ep.emit('topic_html', [topicUrl, res.text]);
        });
    });
  });

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 多版本 Node.js 使用 Workflow

    NodeJS 成为新一届的版本帝后,需要预编译的模块常常更新不够及时,就会出现我这样上班时间搞环境 ,那么如何保持一机多版本继续使用低版本的 NodeJS 运行...

    郑家乐
  • 一次 Node.js 内存溢出

    因为内存上限设置不合理,引起的内存溢出问题。之前压测时候只关注了是否存在内存泄露与cpu占用,而忽视了内存占用这个问题。对于部署服务时,要根据机器的内存上限以及...

    腾讯IVWEB团队
  • TensorFlow入门(3):使用神经网络拟合N元一次方程

    现实中大部分情况是不能简单使用 N 元一次方程这样的公式表达的,神经网络的出现,给这类问题提供了一个很好的解决方法。本文继续给出一个简单的例子,使用 Tenso...

    谭正中
  • 推荐算法之协同过滤

    推荐算法在个性化领域有着广泛的应用,粗略统计,所涉及到的学科包括人工智能、机器学习、认知科学、信息抽取、数据挖掘、预测理论、近似理论,甚至是管理科学、市场营销和...

    刘建银
  • 自己部署 Node.js 版本的 Wafer2 Demo

    自行部署适用于想将腾讯云 Wafer SDK 和 Demo 部署在自己的服务器上以获得更高的灵活性和操纵权限的用户。部署过程需要从 0 开始搭建线上环境,需要有...

    Jason
  • 使用 Node.js 实现一个简单的 ZooKeeper 客户端

    Zookeeper 是一个分布式的、开源的协调服务,用在分布式应用程序中。它提出了一组简单的原语,分布式应用程序可以基于这些原语之上构建更高层的分布式服务用于实...

    腾讯IVWEB团队
  • 编写原生 Node.js 模块

    当 Javascript 的性能遇到瓶颈,或者需要增强 Javascript 能力的时候,就需要依赖native模块来实现了。应用场景日常工作中,我们经常需要将...

    腾讯IVWEB团队
  • 通过 WeCOS 进行小程序瘦身

    尽管 4 月份微信官方将小程序的大小限制从 1M 放开到 2M,但是对于使用大量图片的小程序(电商等)来说,2M 的限制还是显得拮据。基于这种场景,腾讯云微信小...

    Jason
  • TensorFlow入门(1):求N元一次方程

    今年以来,人工智能成为一个时代热点,同时 TensorFlow 1.0 的发布后,我也想蹭蹭时代的热点,初步学习一下神经网络和机器学习,在这里把成果以初学者的方...

    谭正中
  • 十个书写Node.js REST API的最佳实践(上)

    我们会通过本文介绍下书写Node.js REST API的最佳实践,包括各个主题,像是命名路由、认证、黑盒测试以及对相关资源使用合适的缓存头。

    张徐辰

扫码关注云+社区

领取腾讯云代金券