🚀🚀NODE爬虫,搞起~

1,201 阅读3分钟

背景

 说到爬虫,大家想到的大多都是python。其实使用NodeJS也很适合写爬虫。针对一些简单,高效的小爬虫,Javascriptpython更加合适。因为Javascript自带异步,能同时爬取多张网页内容比python更高效。但是python生态更加完整(主要是我还不会python😭)


咋爬?

  • 确定爬取对象(选一个种子URL)  就近取材就掘金的推荐页面,思路大概就是通过推荐页面的前面20篇博客,然后去详情获取数据。
//1. 推荐API
    //URL
    https://apinew.juejin.im/recommend_api/v1/article/recommend_all_feed
    //参数
    {
      id_type: 2,
      client_type: 2608,
      sort_type: 200,
      cursor: '0',
      limit: 20
    }
// 2. 详情API
https://juejin.im/post/【article_id】
  • 安装环境  我此处是KOA框架的环境,并且安装了babel支持了ES6语法。
  • 编码,爬取页面数据并分析
    思路很简单,把页面当作一个个的get请求,加载之后,使用cheerio获取页面内的数据,然后使用fs方法写入到txt文件内。
    cheerio是为服务器特别定制的,快速、灵活、实施的jQuery核心实现。中文文档地址附上,具体API自行查看。

(function() {
const fs = require('fs');
const axios = require('axios');
const cheerio = require('cheerio');
// 使用AXIOS获取推荐LIST数据
axios
  .post(
    'https://apinew.juejin.im/recommend_api/v1/article/recommend_all_feed',
    {
      id_type: 2,
      client_type: 2608,
      sort_type: 200,
      cursor: '0',
      limit: 20
    }
  )
  .then(async({ data: { data } }) => {
    if (data.length === 0) {
      console.log('没数据' + data);
      return false;
    }
    for (let i = 0; i < data.length; i++) {
      //阻塞一个个的获取每个详情内容
      //主要是因为我想按列表顺序排列数据
      const res = await axios.get(
       //文章ID是我自行查看API分析所得
        data[i].item_info.url ||
          ('https://juejin.im/post/' +
            (data[i].item_info.article_id || data[i].item_info.advert_id))
      );
      //cheerio上场
      const $ = cheerio.load(res.data, {
        normalizeWhitespace: false,
        xmlMode: false,
        decodeEntities: false
      });
      fs.appendFile(
        './spider/result.txt',
        //获取article标签内的html内容
        //自己可以先观察页面具体情况,在做数据收集
        $('article').html(),
        'utf8',
        err => {
          if (err) throw err;
          console.log('数据已被追加到文件');
        }
      );
    }
  })
  .catch(error => {
    console.log(error);
  });
})();


爬了又爬

 想到双12,我就想去爬一下淘宝数据,结果过程有点复杂。还是按照老的方法取分析

(function() {
  const fs = require('fs');
  const axios = require('axios');
  const cheerio = require('cheerio');
  //处理中文乱码
  const iconv = require('iconv-lite');
  const util = require('util');
  axios({
    methods: 'get',
    url:
      'https://list.tmall.com/search_product.htm?spm=a221t.1476805.cat.19.52006769d615Pr&cat=54290107&q=%E4%BC%91%E9%97%B2%E5%A5%97%E8%A3%85',
    headers: {
      'content-type': 'text/html;charset=GBK'
    }
  })
    .then(res => {
      if (!res.data) {
        console.log('数据为空,无法追加');
        return false;
      }
      const contentBinary = iconv.decode(
        Buffer.from(util.inspect(res.data), 'binary'),
        'GBK'
      );

      const $ = cheerio.load(contentBinary, {
        normalizeWhitespace: true,
        decodeEntities: false
      });
      console.log($('.productTitle a').attr('title'));
      console.log($('em').attr('title'));
      fs.appendFile(
        './spider/taobao.txt',
        $('.productTitle a').attr('title'),
        'utf8',
        err => {
          if (err) throw err;
          console.log('数据已被追加到文件');
        }
      );
    })
    .catch(err => {
      if (err) throw err;
    });
})();

结果打印出来的中文全是乱码,各种百度搜索,然后大多都是推荐iconv-lite来处理。但是我这里不生效,不知道为啥。有大佬懂的指点一下


放弃?那是不可能

 上面的方法,爬取淘宝网站的内容都是中文乱码。后面我又发现了一个很厉害的工具Puppeteer,附上gitHub地址

Puppeteer 是一个控制 headless ChromeNode.js API 。它是一个 Node.js 库,通过 DevTools 协议提供了一个高级的 API 来控制 headless Chrome。在浏览器中手动完成的大多数事情都可以通过使用 Puppeteer 完成。

Headless Chrome是啥?其实是在无界面的环境中运行 Chrome。并且能通过命令行或者程序语言操作,无需人的干预,运行更稳定

;(async function() {
    const cheerio = require('cheerio');
    const puppeteer = require('puppeteer');
    const fs = require('fs');
    const browser = await puppeteer.launch({
      headless: false, // 有浏览器界面启动
      slowMo: 100, // 放慢浏览器执行速度,方便测试观察
      args: [ // 启动 Chrome 的参数
        '–no-sandbox',
        '--window-size=1280,960'
      ]
    });
    const page = await browser.newPage();
    //打开新页面 淘宝需要抓去数据的页面URL
    await page.goto(
      'https://list.tmall.com/search_product.htm?spm=a221t.1476805.cat.19.52006769d615Pr&cat=54290107&q=%E4%BC%91%E9%97%B2%E5%A5%97%E8%A3%85'
    );
    //也可以用page.evaluate然后使用document去获取dom数据
    //获取页面的html
    const html = await page.content();
    //使用cheerio分析页面数据
    const $ = cheerio.load(html, {
      normalizeWhitespace: true,
      decodeEntities: false
    });
    const goods = [];
    const price = [];
    const saleNum = [];
    $('.productTitle a').each((i, elem) => {
      goods.push($(elem).attr('title'));
    });
    $('.productPrice em').each((i, elem) => {
      price.push($(elem).attr('title'));
    });
    $('.productStatus em').each((i, elem) => {
      saleNum.push($(elem).text());
    });
    //将商品名称,价格和月成交量拼接,并且写入CSV文件
    const result = goods.reduce((current, item, i) => {
      return `${current}\n${item}${price[i]},${saleNum[i]}`;
    }, '');
    fs.appendFile(
      './spider/tmall.csv',
      '商品,价格,月成交' + result,
      'utf8',
      err => {
        if (err) throw err;
        console.log('数据已被追加到文件');
      }
    );
    await page.close();
    await browser.close();
})();

由于这是使用chrome浏览器去获取页面数据,就不存在中文乱码问题。🎉 🎉 🎉 🎉


最后

 到这里,基本的小爬虫已经就会咯。但是在淘宝网站里面,搜索只提供第一页数据,分页就需要登录。但是只能用js自行去登录了,然后再去爬数据了。

  // 思路大致如下,输入用户和密码,点击登录
  await page.type("#username",config.username);
  await page.type("#password",config.password);
  await page.click('#login');
  console.log("Login Secuessed...");

喜欢的大佬,点个赞👆👆👆

喜欢的大佬,点个赞👆👆👆

喜欢的大佬,点个赞👆👆👆

 图片不见了。。。