爬虫相信大家都知道,这里我们从一个空的文件夹开始,也来写一写我们自己的爬虫程序吧。

github入口

下一篇——数据分析篇入口

爬虫毕竟涉及到数据的爬取,所以其实有一个道德的约束,那就是Robots协议,也就是爬虫协议,爬虫程序在爬取网站数据之前,会先看看是否存在robots.txt文件,假如有,会在这个文件允许的范围内进行爬取。像著名的百度,谷歌等搜索引擎,都是遵循这一道德规约的。

好了,闲话少说,开始我们的编程之旅吧。

准备工作:

①、node环境

②、一个空文件夹

准备工作是不是很简单?接下来,你需要能被爬取到数据的数据源。也就是一串URL,这里我选择对前端开发这个岗位做一次数据采集与分析。选择的对象呢——是猎聘网,希望别打我 = =

我们创建好文件夹之后,先去猎聘网,搜索一下前端开发,看看它们页面的数据是怎样的。

大概每页40条,很多很多页。。。除了前端开发这个关键字以外其他一律选择不限。

这时候打开NetWork面板,在它的分页上随便点一页,看看此时新出来这40条数据是怎么来的。

此时你可以发现有一个数据包,将整个页面html返回给你。

而这样的一个页面就是我们的数据源。找到这个数据包的同时,别忘了把它的URL拷贝出来。

接下来第一步,将这一页的40条招聘信息数据爬出来。

先在空文件夹下创一个app.js。里面写上一句‘hello world’,并在终端(vscode或webstorm的terminal或者直接打开cmd,git bash啥的都可以),运行最熟悉的一句命令——node app.js。如下:

  这样我们的node程序可以正常运行了。

接下来,将我们的这串URL拷贝进app.js,再引入一下https这个模块(因为刚好我们要爬取的网页是带数字证书的)。

代码如下:

// console.log('你好啊!my name is dorsey');

const https = require('https');

let url = 'https://www.liepin.com/zhaopin/?init=-1&headckid=0417b67c8d823dcb&fromSearchBtn=2&sfrom=click-pc_homepage-centre_searchbox-search_new&ckid=0417b67c8d823dcb&degradeFlag=0&key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&siTag=D_7XS8J-xxxQY6y2bMqEWQ%7EfA9rXquZc5IkJpXC-Ycixw&d_sfrom=search_fp&d_ckId=466b672969a37b2deaf20975f4b05e7c&d_curPage=0&d_pageSize=40&d_headId=466b672969a37b2deaf20975f4b05e7c&curPage=1';

https.get(url, function (res) {

res.on('data', function (chunk) {

console.log(chunk);

});

res.on('end', function () {

console.log('数据包传输完毕');

});

})

代码很简单,通过https模块去get我们这个URL的链接,从这个链接不断下载一个个的字节流数据过来,等到数据流传输完了,监听end,就可以把这些字节码打包成一个完整的数据包,将字节码转成字符,就是我们所需要的数据。

我们还是通过node app.js去运行我们的程序。

可以看到一个个的包。我们将这些流缓冲数据合并成一个包,并转化成我们看得懂的字符串。此时代码需要做一些小改造。变成这样:

// console.log('你好啊!my name is dorsey');

const https = require('https');

let url = 'https://www.liepin.com/zhaopin/?init=-1&headckid=0417b67c8d823dcb&fromSearchBtn=2&sfrom=click-pc_homepage-centre_searchbox-search_new&ckid=0417b67c8d823dcb&degradeFlag=0&key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&siTag=D_7XS8J-xxxQY6y2bMqEWQ%7EfA9rXquZc5IkJpXC-Ycixw&d_sfrom=search_fp&d_ckId=466b672969a37b2deaf20975f4b05e7c&d_curPage=0&d_pageSize=40&d_headId=466b672969a37b2deaf20975f4b05e7c&curPage=1';

https.get(url, function (res) {

let chunks = [],

size = 0;

res.on('data', function (chunk) {

chunks.push(chunk);

size += chunk.length;

});

res.on('end', function () {

console.log('数据包传输完毕');

let data = Buffer.concat(chunks, size);

console.log(data);

let html = data.toString();

console.log(html);

});

})

再node app.js运行一下,此时可以看到控制台打印的就是我们之前在NetWork那里看到的那个页面,里面有我们需要的40条数据。

这时候得回到页面,看看存放了招聘信息的那些关键数据放在哪个标签下面。可以看到每一条的关键信息都存在一个类名为job-info的div里,里面包含职位信息condition,招聘公司信息company-info。此时需要将这里的数据提取出来。

那如何提取出来?此时看到这个你可能想,要是有个JQuery就好了,通过选择器来选到对应的信息元素,但注意,这不是页面,这是node,那怎么办?

要相信,假如我们还是处于小白及进阶阶段,你遇到过的问题一定也是很多人也会遇到的问题,也往往能搜到相应的解决方案。这里就有一个很好很实用的package包,那就是cheerio。它相当于node环境中的JQuery,用来爬虫,爬取网页特定信息,最适合不过了。

首先当然是安装一下。

  接下来,边对照着猎聘网的对应位置,通过写JQuery代码的方式,来一步步选择到目标数据,JQuery选择器如何选到对应DOM元素的,相信你们都会了,代码的改造如下。

// console.log('你好啊!my name is dorsey');

const https = require('https');

const cheerio = require('cheerio');

let url = 'https://www.liepin.com/zhaopin/?init=-1&headckid=0417b67c8d823dcb&fromSearchBtn=2&sfrom=click-pc_homepage-centre_searchbox-search_new&ckid=0417b67c8d823dcb&degradeFlag=0&key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&siTag=D_7XS8J-xxxQY6y2bMqEWQ%7EfA9rXquZc5IkJpXC-Ycixw&d_sfrom=search_fp&d_ckId=466b672969a37b2deaf20975f4b05e7c&d_curPage=0&d_pageSize=40&d_headId=466b672969a37b2deaf20975f4b05e7c&curPage=1';

https.get(url, function (res) {

let chunks = [],

size = 0;

res.on('data', function (chunk) {

chunks.push(chunk);

size += chunk.length;

});

res.on('end', function () {

console.log('数据包传输完毕');

let data = Buffer.concat(chunks, size);

let html = data.toString();

let $ = cheerio.load(html);

let result = [];

$('.sojob-list').find('.job-info').each(i => {

let map = {};

// 个人基本信息

map.name = $('.job-info').eq(i).find('h3').attr('title');

let baseOthersInfo = $('.job-info').eq(i).find('.condition').attr('title');

baseOthersInfo = baseOthersInfo.split("_");

map.reward = baseOthersInfo[0];

map.area = baseOthersInfo[1];

map.experience = baseOthersInfo[2];

// 公司信息

let companyTagDom = $('.company-info').eq(i).find('.temptation').find('span');

let companyTag = [];

companyTagDom.each(i => {

companyTag.push(companyTagDom.eq(i).text());

});

let companyInfo = {

name: $('.company-info').eq(i).find('.company-name a').attr('title'),

href: $('.company-info').eq(i).find('.company-name a').attr('href'),

type: $('.company-info').eq(i).find('.industry-link a').text(),

tag: companyTag.join(',')

}

map.company = companyInfo;

result.push(map);

map = {};

});

console.log(result);

});

});

运行下app.js,(node app.js)再看下控制台:

可以看到我们需要的目标数据已经被load出来了。

此时你可能有疑惑了,写了这么一大段代码,总是去console.log打印日志来排错,费时又费力,能不能跟写前端页面代码一样,在浏览器上直接打断点。

答案是肯定的,此时,我们还是运行app.js,只不过命令稍加变动,变成:

node --inspect-brk app.js

终端输入命令之后运行,并打开浏览器的:

chrome://inspect/#devices

此时,你可以看到Target目标调试对象:

这样就跟在浏览器打断没有区别了。是不是很cool?

好了扯远了,继续我们的node编程。

我们刚刚拿到的是一个数据包,40条数据,也就是一个分页的数据,可是要拿多个分页怎么办?能否再次合并成一个数据包或者数据文件?答案是肯定的。别忘了,我们现在的舞台不是浏览器,而在于更为广阔的系统平台本身或者更准确的一点是一台具备完整系统功能的JVM上,所以读写文件,甚至读写数据库这个利器才是我们的根本。

简单就不去搞一个mongoDB了,直接写进一个txt文件。这时候代码需要补充一下文件模块依赖 fs 以及文件写入的一部分代码,如下:。

const fs = require('fs');

// ...

fs.writeFile('./cache/jobs.txt', JSON.stringify(result), { 'flag': 'a' }, function(err) {

if(err) throw err;

console.log('写入成功');

});

这样写虽然可以,但有一个问题,因为我们写入txt文件的时候,每个数据包,也就是result都是一个数组,这样直接转成字符串增量写入txt会出现一个问题。看看哈。

也就是说,这时候虽然写进去没问题,但是最终读出来却不是JSON格式的数据,所以在每个数据包写入的时候,我们得做一点点字符串替换,就比如将:

][ 替换成 ,

所以代码需要改造成这样,比如说我们这里暂且设置是10个数据包,后期改造参数传递就好了:

let dataStr = JSON.stringify(result).trim().replace(/^\[/, curPage == 1 ? '[' : '').replace(/\]$/, curPage == 10 ? ']' : ',');

fs.writeFile('./cache/jobs.txt', dataStr, { 'flag': 'a' }, function(err) {

if(err) throw err;

console.log('写入成功');

});

但这时候URL没变,你拿到的数据包虽然有10个,但都是一样的数据包,这显然不是我们想要的,所以又得回到猎聘网,看看他们分页改变时是哪些关键参数改变了。仔细观察可以发现URL参数变动的是这两个。

  所以我们将这两个参数抽出来,模拟一下URL入参传参,再次进行爬虫,代码需要做改造。由于这部分数据采集尽管有内部分工,但完成的目标是一致的,所以我们可以定义一个class,来将整个的过程封装起来。如下:

const

https = require('https'),

fs = require('fs'),

cheerio = require('cheerio');

class crawlData {

constructor ( page ) {

this.currentPage = 1;

this.page = page;

this.baseUrl = 'https://www.liepin.com/zhaopin/?isAnalysis=&dqs=&pubTime=&salary=&subIndustry=&industryType=&compscale=&key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&init=-1&searchType=1&headckid=b41b3a1f788e456c&compkind=&fromSearchBtn=2&sortFlag=15&ckid=e0769e995864e9e1&degradeFlag=0&jobKind=&industries=&clean_condition=&siTag=D_7XS8J-xxxQY6y2bMqEWQ%7EfA9rXquZc5IkJpXC-Ycixw&d_sfrom=search_prime&d_ckId=ec6119ede4a8421d04cde68240799352&d_curPage=';

this.init();

}

init () {

let _self = this;

let time = setInterval(function () {

if(_self.currentPage > _self.page) {

clearInterval(time);

}

else{

console.log('第 ' + _self.currentPage + ' 个爬虫请求发出');

_self.getDataPackage(_self.baseUrl + (_self.currentPage + 1) + '&d_pageSize=40&d_headId=ad878683a46e56bca93e6f921e59a95&curPage=' + _self.currentPage, _self.currentPage);

_self.currentPage ++;

}

}, 1000 * 5);

}

getDataPackage (url, curPage) {

console.log(url);

let _self = this;

https.get(url, function(response){

var chunks = [];

var size = 0;

response.on('data',function(chunk){

chunks.push(chunk);

size += chunk.length;

});

response.on('end',function(){

let data = Buffer.concat(chunks, size);

let html = data.toString();

let $ = cheerio.load(html);

let result = [];

$('.sojob-list').find('.job-info').each(i => {

let map = {};

// 个人基本信息

map.name = $('.job-info').eq(i).find('h3').attr('title');

let baseOthersInfo = $('.job-info').eq(i).find('.condition').attr('title');

baseOthersInfo = baseOthersInfo.split("_");

map.reward = baseOthersInfo[0];

map.area = baseOthersInfo[1];

map.experience = baseOthersInfo[2];

// 公司信息

let companyTagDom = $('.company-info').eq(i).find('.temptation').find('span');

let companyTag = [];

companyTagDom.each(i => {

companyTag.push(companyTagDom.eq(i).text());

});

let companyInfo = {

name: $('.company-info').eq(i).find('.company-name a').attr('title'),

href: $('.company-info').eq(i).find('.company-name a').attr('href'),

type: $('.company-info').eq(i).find('.industry-link a').text(),

tag: companyTag.join(',')

}

map.company = companyInfo;

result.push(map);

map = {};

});

let dataStr = JSON.stringify(result).trim().replace(/^\[/, curPage == 1 ? '[' : '').replace(/\]$/, curPage == _self.page ? ']' : ',');

fs.writeFile('./cache/jobs.txt', dataStr, { 'flag': 'a' }, function(err) {

if(err) throw err;

console.log('写入成功');

});

});

});

}

}

// 一个数据包40条,这里是99 * 40 = 3960条

new crawlData(99);

接下来,开始爬取数据了。

这里设置99条的原因是因为猎聘网最大的分页是100,也就是只保留了100页的分页数据。再看看此时jobs.txt文件的大小,有1M多的数据。

看看打印在页面上的数据哈。

可以看到有3960条数据,虽然还不是很多,但已从零开始,完成了一个基本的数据采集流程,不是吗?

第一篇的数据采集就暂且到这,等待后续的数据分析吧。

node爬取app数据_从零开始写一个node爬虫(上)—— 数据采集篇相关推荐

  1. node爬取app数据_在电销行业中,运营商大数据究竟起着怎样的作用

    联通运营商已经执行大数据精确获客业务流程.运营商大数据精确获客业务流程能够协助不一样的领域,不一样的公司节省获客推广营销成本费,均值能够协助每一个公司节省营销推广固定成本的30%-50%,而且获客率能 ...

  2. node爬取app数据_使用node.js如何爬取网站数据

    数据库又不会弄,只能扒扒别人的数据了. 搭建环境: (1).创建一个文件夹,进入并初始化一个package.json文件. npm init -y (2).安装相关依赖: npm install -- ...

  3. node爬取app数据_node爬取拉勾网数据并导出为excel文件

    前言 之前断断续续学习了node.js,今天就拿拉勾网练练手,顺便通过数据了解了解最近的招聘行情哈!node方面算是萌新一个吧,希望可以和大家共同学习和进步. 一.概要 我们首先需要明确具体的需求: ...

  4. node爬取app数据_Nodejs使用cheerio爬取网站数据

    Cheerio: Cheerio 是一个Node.js的库, 它可以从html的片断中构建DOM结构, 然后提供像jquery一样的css选择器查询 本文实现一个抓取类别列表的功能. 一丶圈点勾画: ...

  5. python爬取flash数据_爬取flash数据

    关于html爬取数据的文章已经有很多了,我今天主要和大家交流的是如何爬取flash网页的数据.这方面资料相对比较少,主要是html5兴起后现在flash站很少了,不过用于技术研究还是可以尝试一下,这篇 ...

  6. python爬取app聊天信息_手把手教你爬取手机app中的信息

    使用工具:Fiddler+基础爬虫 Fiddler是一个抓包神器,用来检查电脑和互联网之间所有的通讯内容,而且比较简单容易上手,显示的格式也比较友好. 网页基本都会爬了,现在开始要想想如何去爬手机ap ...

  7. Python爬虫实战:手机APP数据抓取分析!谁说不能爬取app数据的?

    大多数手机APP里面返回的是json格式数据,或者一堆加密过的数据 .这里以超级课程表APP为例,使用python抓取超级课程表里用户发的话题.主要是练习python爬取app的一些方式和技巧. 1. ...

  8. java爬取网页数据_利用Python做数据分析—对前程无忧数据类岗位进行分析

    引言 随着时代的发展,我国在各行各业都需要大量的人才引进,处于近几年最热门的行业也称"最火行业":大数据.数据分析.数据挖掘.机器学习.人工智能,这五门行业各有不同又互有穿插.近几 ...

  9. python爬取客流数据_【python爬取雅虎财经数据】“五一”和广交会客流叠加 广州出入境客流呈“双高峰”...

    [python爬取雅虎财经数据]"五一"和广交会客流叠加 广州出入境客流呈"双高峰" 发布时间:2020-10-13 18:06:00 阅读量:650 作者:乔 ...

最新文章

  1. css position的父级,css position absolute 相对于父元素的设置方式
  2. idea 在tomcat中部署的时候 莫名其妙的错误
  3. Directx 顶点和顶点缓存
  4. C与C++中的extern与static、extern C与__cplusplus的作用
  5. Vue3.x 使用ref和reactive、toRef
  6. oracle 11g安装时设密码 database control,安装oracle 11g 保护Database Control时出错,Database Control已在非安全模式下启动...
  7. Hive的数据模型-管理表
  8. Dedecms 最新版漏洞收集并复现学习
  9. bat从数组中找出相同数字并删除_全网把Map中的hash()分析的最透彻的文章,别无二家...
  10. Matplotlib - bar(条形图)
  11. T-SQL: Batches
  12. Android项目开发—GeoQuiz
  13. 手撕深度学习框架,原理很简单
  14. python和java学哪个好-Python和Java学哪个好就业?
  15. 力扣题目系列:605. 种花问题
  16. 从团购的“占便宜”心态说起
  17. Linux运维面试题
  18. 【爬虫】用Python爬取《Nature》杂志文章的题目、摘要、下载地址
  19. 【houdini 基础】Ramp 参数
  20. 必备技能:图解用电烙铁焊接电路

热门文章

  1. 10019---层次选择器
  2. 2021最新Spring Security知识梳理
  3. gcc ------ 编译与链接选项及CFLAGS、LDFLAGS、LIBS
  4. 测试案例(五个案例)
  5. USB OTG(Host) 、 USB ADB(Device)、DWC3 Charge
  6. 锐达机械对H型钢抛丸机的维修调整工作
  7. 《大明王朝1566》台词摘录
  8. 在windows 10上使用qemu安装Windows 10虚拟机
  9. 产品销售份额数据统计流程图模板分享
  10. 【转】CCIE一年后的心语