Node.js的简易爬虫

来源:互联网 发布:淘宝买东西流程 编辑:程序博客网 时间:2024/06/05 09:32

前几天,公司的一些网编和网推们需要扒某个页面内关于全国药店的店铺名地址电话,我一看,好家伙,四川省就足足有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; // idlet str = ''; // 下一页后的新地址let addressInfo = []; // 地址信息let end = ''; // 结束页,通过正则replace a标签的hreflet 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 超链接跳转到新页面,这些处理日后再议啦~~

原创粉丝点击