Node.js的简易爬虫

前几天,公司的一些网编和网推们需要扒某个页面内关于全国药店的店铺名地址电话,我一看,好家伙,四川省就足足有93页的数据量,一页60条数据,靠人工 Ctrl+C + Ctrl+V

这里写图片描述

身为一名懒比,能偷懒当然不能出力了啊!

要数据,当然要【爬】【虫】!

不过身为一名苦逼的菜鸟 html狗,你和我说什么 python,我选择狗带

这里写图片描述

所幸啊,我们有一个好玩儿的东西,叫做 Node.js

那么就开始动手吧!
(文件已上传,源码请移步 同性交友平台)。

爬虫主要是去获取HTML里的data,然后正则输出你所需要的信息,不过因为有一个神奇的依赖包 cheerio.js 的存在,咱们可以在node里直接像 jQuery 一样用 美金 的力量操作DOM元素。

关于 cheerio.js 的操作方法,同学们可以移步 这儿,可以发现,它的操作方法以及相应的API简直就是和 jQuery 一毛一样,那妥了,接下来就是分析页面结构,就可以开始扒了!

所以,我们需要先 npm 一下这个依赖包

npm i cheerio -s

安装好以后,就可以开始编写 js 啦。

贴上源码,并做解释:

const http = require('http'); // 引入http模块
const fs = require('fs'); // 引入fs模块
const cheerio = require('cheerio'); // 引入cheerio模块
let i = 0; // id
let str = ''; // 下一页后的新地址
let addressInfo = []; // 地址信息
let end = ''; // 结束页,通过正则replace a标签的href
let page = 0; // 当前页
const url = 'http://www.fuyaotang.com/a110000'; // 要扒的页面的第一页

function fetchPage(x) {
  startRequest(x);
};

function startRequest(x) {
  http.get(x, (res) => { // 获取数据而不是上传数据,所以用GET请求即可
    let html = '';
    res.setEncoding('utf-8'); // 防止中文乱码
    res.on('data', (chunk) => {
      html += chunk; // 获取到的html标签,拼接到html变量上
    });
    res.on('end', () => {
      let $ = cheerio.load(html); // 声明cheerio
      let infoArray = $('div.related a'); // 获取所有的内容
      infoArray.each((index, item) => {
        addressInfo.push({ // 添加到数组中
          storeName: infoArray.eq(index).children('h3').text().trim(),
          address: infoArray.eq(index).children('p').eq(0).text().trim(),
          telNum: infoArray.eq(index).children('p').eq(-1).text().trim(),
          id: i += 1
        });
      });
      // console.log(addressInfo);
      end = $('div.list a').eq(-2).attr('href'); // 下一页地址
      end = end.substr(end.length - 2).replace(/[_]/g, ""); // 下一页href的正则输出-->获取数值
      let newxtLink = `http://www.fuyaotang.com/${$('div.list a').eq(-2).attr('href')}`;
      str = encodeURI(newxtLink); // encodeURI编码
      if(page < end) {
        page += 1;
        fetchPage(str); // 递归
      } else {
        saveContent($, addressInfo); // 全部结束后,保存数据
      }
    });
  }).on('error', (err) => {
    console.log(err); // 报错信息打印到DOC
  })
}

function saveContent($, data) {
  let storeName = '',
      address = '',
      telNum = '';
  data.forEach((item, index) => {
      storeName += data[index].storeName + '\r\n'; // windows需要\r\n换行
      address += data[index].address + '\r\n';
      telNum += data[index].telNum + '\r\n';
  });
  // 因为他们的EXCEL需求是要一列一列的输出数据,因此将每一列数据保存到一个文件中,可以直接Ctrl+a复制粘贴,其他的数据操作留待他们在EXCEL自己操作了
  fs.appendFile('./data/' + $('.filtertag').find('.cur').text().trim() + '_店铺.txt', storeName, 'utf-8', (err) => {
    if (err) {
      console.log(err)
    }
  })
  fs.appendFile('./data/' + $('.filtertag').find('.cur').text().trim() + '_地址.txt', address, 'utf-8', (err) => {
    if (err) {
      console.log(err)
    }
  })
  fs.appendFile('./data/' + $('.filtertag').find('.cur').text().trim() + '_电话.txt', telNum, 'utf-8', (err) => {
    if (err) {
      console.log(err)
    }
  })
};

fetchPage(url); // 执行函数

这里必须要说一句,不要通过 Babel 直接用 ES6 简直不要再美唧唧,手动滑稽。

因为只是简单的数据需求,因此仅仅写到这儿,更多的功能,包括下一页涉及的是点击事件发送 ajax 直接更新 DOM树 而不是 href 超链接跳转到新页面,这些处理日后再议啦~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值