【前端实践系列之十二】✖💨💔🌊五十行代码写一个Node爬虫!

314 阅读3分钟

这是我参与更文挑战的第19天,活动详情查看: 更文挑战 !

👽 概论

近期突然想试着做下爬虫,作为一名土生土长的前端人,用python去做这件事自然是不会的。得益于NodeJs的存在,JavaScript在非浏览器环境下也能轻松完成这种需求。

辗转学习了一圈,总算能实现一些简单的爬虫任务,下面就和大家分享下这次爬虫经历。通过这篇文章,不敢说大家能让彻底搞懂爬虫或者完成复杂的爬虫任务,但实现入门还是没有问题的。所以这次分享也就力求用最精简的代码,来完成入门介绍。大家入门之后如果有更好的想法或者心得,欢迎指导交流,毕竟我也只是一位爬虫新手。

👽 工具介绍

🙋NodeJs: js运行时,大家都懂,不多说了;

🙋Express:NodeJs下的一款web应用程序开发框架,基于此我们可以搭建一个简易的本地服务器;

🙋superagent:NodeJs下的一款请求库,相对于node中的http库它会更加灵活易用一些,此次开发中我们用其来提交请求;

🙋cheerio:NodeJs下的一款DOM操作库,可以看做是node中的jquery。

👽 项目初始化

在本地新建好一个项目后,我们可以依次执行以下命令:

// 项目初始化
npm init -y

// 安装依赖
npm i express superagent cheerio

👽 express服务器搭建

新建app.js,在其中简易配置express:

//引入express
const app = require('express')();


let data = [];//定义待返回的数据

app.get('/', async (req, res, next) => {//定义路由与对应返回的数据
  res.send(data.length > 0 ? data : 'HelloWorld');
});

app.listen(3000, () => {
  //设置端口为3000并进行监听
  console.log('app started at port http://localhost:3000...');
});

此时执行启动命令node app.js,访问对应地址即可看见响应内容:

image.png

Tips: 
    如果每次修改保存app.js之后都需要重新运行启动命令,页面才能更新。这其实是一个很麻烦的过程。
    这一重复过程其实完全可以通过工具自动处理:nodemon。
    nodemon是用来监听js页面变化并自动执行node命令的一款工具,用法也非常简单。
    只需全局安装nodemon,完成之后执行 nodemon app.js即可。

👽 提交网络请求

这里我们以爬取Boss页面为例,直接复制待爬取页面的url与cookie,通过superAgent发送请求:

//引入superAgent
const app = require('superAgent');

function getHtml(url, cookie) {
  superagent
    .get(url)
    .set('Cookie', cookie)
    .end((err, res) => {
      if (err) {
        console.log(`页面抓取失败: ${err}`);
      } else {
        //此处的res.text可看做原请求返回的页面
        data = cookData(res.text);//将处理后的页面数据赋给data,cookData此方法我们随后定义
      }
    });
}

let url =
  'https://www.zhipin.com/job_detail/?query=%E8%85%BE%E8%AE%AF&city=100010000&industry=&position=100999';

let cookie ='xxxxxxx';

getHtml(url,cookie)//执行方法

👽 解析页面数据

假设我们是要爬取boss中前端职位对应的二级页面链接数据。解决的整体思路就是:首先审查boss原网页,分析下dom结构,然后再通过cheerio去选中对应dom,提取所需数据。

如下图,我们可以清晰地看到,primary-box即为我们的目标元素。

image.png

//引入cheerio
const cheerio = require('cheerio');

function cookData(res) {
  let data = [];

  let $ = cheerio.load(res);//将响应到的页面数据解析为cheerio对象

  // 获取目标元素上的数据
  $('div.primary-box')
    .each((i, node) => {
      data[i] = node.attribs.href;
    });

  return data;
};

到这一步我们就算大功告成了,页面上可以看到返回的数据效果:

image.png

👽 完整代码

const app = require('express')();
const cheerio = require('cheerio');
const superagent = require('superagent');

let data = []; 

let url =
  'https://www.zhipin.com/job_detail/?query=%E8%85%BE%E8%AE%AF&city=100010000&industry=&position=100999';
let cookie ='xxxxx';

function cookData(res) {
  let data = [];

  let $ = cheerio.load(res); 
  $('div.primary-box').each((i, node) => {
    data[i] = node.attribs.href;
  });

  return data;
}
function getHtml(url, cookie) {
  superagent
    .get(url)
    .set('Cookie', cookie)
    .end((err, res) => {
      if (err) {
        console.log(`页面抓取失败: ${err}`);
      } else {
        data = cookData(res.text); 
      }
    });
}

getHtml(url, cookie);

app.get('/', async (req, res, next) => {
  res.send(data.length > 0 ? data : 'HelloWorld');
});

app.listen(3000, () => {
  console.log('app started at port http://localhost:3000...');
});

👽 结语

如果是无需在前端查看,项目中的express也是可以不需要的,通过fs库将处理后的数据存入本地也不失为一种好选择。现实中的爬虫需求当然不会这么简单,前路漫漫,大家一起加油🚀🚀🚀!