用node.js写一个简单爬虫,并将数据导出为 excel 文件
引子
最近折腾node,最开始像无头苍蝇一样到处找资料,然而多数没什么卵用,都在瞎比比。在一阵瞎搞后,我来分享一下初步学习node的三个过程:
1 撸一遍NODE入门,对其有个基本的了解;
2 撸一遍cnode.js社区管理员写的包教不包会node课程,内容量相对于 NODE入门多了很多,特别是这个可能更注重实际项目的构建方式。
3 通读一遍朴灵的《node.js深入浅出》,配合着api一起看(还在继续..药不能停)。
尽看书总是有一种茫然不知所措的感觉,就像手中有一把锋利的钢刀,却不知该如何挥舞。之前学python写了一个爬虫脚本(已经忘得差不多了),那么用牛逼的node肯定也不在话下。于是,花了一个下午,爬取了安居客武汉站的新房数据,亮点是把爬取到的数据通过excel导出来,方便查看。如果哪天有空,可以用echart 做成漂亮的图表,应该是一个good idea。
功能实现简述
功能其实很简单,通过 superagent 模块模拟浏览器向服务器发送请求,利用 cheerio 模块将获得的响应数据转化为我们熟悉的 html ,并且能用如 jQuery 般的使用选择器获取我们想要的数据,最后通过 node-xlsx 模块将数据导出为 excel 文件。是不是很简单呢?
遇到的小坑
1、 node 内建的http 模块,使用http.get(url,cb)方法只能获取静态文件,而多数网站的内容是动态加载的,这就意味着根本获取不到内容啊!!!我真的是一行一行的debug 才反应过来,word天,真是人笨不能怨天。最后通过 superagent 解决了。
2、 通过cheerio.load(html)后,数据们都乖乖的等着我们使用jQuery的方式来获取,我傻逼的独特之处在于,使用$.each(function(i,e){})方法,在内部用$(this)死活拿不到节点,很焦躁啊朋友们。于是又翻了一下API,原来e 是一个dom节点,还得这样用$(e)。你们说我傻逼不?
3、 fs.writeFile 和 fs.createwriteFile ,我还没太明白他们之间的关联,反正第二个方式在本案例中没有用,and 关于什么时候使用同步方法什么时候使用异步方法,谁能告诉我?
const
http = require('http'),
fs = require('fs'),
cheerio = require('cheerio'),
request = require('superagent'),
xlsx = require('node-xlsx'),
url = 'http://wh.fang.anjuke.com/loupan/all/p';
let page = 1,
list = [],
start = '',
fetchPage = ()=> {
start();
};
start = ()=> {
request.get(url + page +'/')
.end((err, res)=> {
if (!err) { // 如果获取过程中没有发生错误
let
html = res.text, // 获取到数据
$ = cheerio.load(html, {decodeEntities: false}), // 加载获取到的 html 数据
$itemMod = $('.key-list').find('.item-mod'),
len = $itemMod.length;
if(len > 0) {
page ++;
$itemMod.each((i, e)=> {
let data = [], // 用来存储抓取的数据
$e = $(e); // 缓存
data.push($e.find('.items-name').text().trim());
data.push($e.find('.status-icon').text().trim());
data.push($e.find('.address').text().trim().replace(/( )*|(.*/g, '').split('(')[0]);
data.push($e.find('.price').text().trim());
data.push($e.find('.tel').text().trim());
data.push($e.find('.address').next('p').find('a').text().trim());
data.push($e.find('.pic>img').attr('src'));
list.push(data);
});
console.log(list.length);
// 通过 xlsx 模块将数据转化成 buffer 对象
let buf = xlsx.build([{name: 'hhh'}, {data: list}]);
// 将 buffer 写入到 my.xlsx 中(导出)
fs.writeFile('my.xlsx', buf, (err)=> {
if(err) throw err;
console.log('File is saved!');
// 回调获取下一页数据
start();
});
}
} else {
console.log('Get data error !');
}
});
};
fetchPage();
截止目前为止,武汉新房的信息总共有 1177 条。
最后吐槽一句,特么武汉房价涨得真特么快,握草!
用node.js写一个简单爬虫,并将数据导出为 excel 文件的更多相关文章
- [NodeJS]使用Node.js写一个简单的在线聊天室
声明:教程来自<Node即学即用>.源代码案例均出自此书.博文仅为个人学习笔记. 第一步:创建一个聊天server. 首先,我们先来写一个Server: var net = require ...
- 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”
这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...
- JS 在页面上直接将json数据导出到excel,支持chrome,edge,IE10+,IE9,IE8,Safari,Firefox
JS 在页面上直接将json数据导出到excel,支持chrome,edge,IE10+,IE9,IE8,Safari,Firefox <html> <head> </h ...
- 使用 Node.js 写一个代码生成器
背景 第一次接触代码生成器用的是动软代码生成器,数据库设计好之后,一键生成后端 curd代码.之后也用过 CodeSmith , T4.目前市面上也有很多优秀的代码生成器,而且大部分都提供可视化界面操 ...
- JS写一个简单日历
JS写一个日历,配合jQuery操作DOM <!DOCTYPE html> <html> <head> <meta charset="UTF-8&q ...
- 基于Node.js实现一个小小的爬虫
以前一直听说有爬虫这种东西,稍微看了看资料,貌似不是太复杂. 正好了解过node.js,那就基于它来个简单的爬虫. 1.本次爬虫目标: 从拉钩招聘网站中找出“前端开发”这一类岗位的信息,并作相应页面分 ...
- 学习用node.js建立一个简单的web服务器
一.建立简单的Web服务器涉及到Node.js的一些基本知识点: 1.请求模块 在Node.js中,系统提供了许多有用的模块(当然你也可以用JavaScript编写自己的模块,以后的章节我们将详细讲解 ...
- C#写一个简单爬虫
最近研究C#的爬虫写法,搞了半天,才在网上很多的写法中整理出了一个简单的demo(本人菜鸟,大神勿喷).一是为了自己记录一下以免日后用到,二是为了供需要朋友参考. 废话不多说,上代码 using Ht ...
- js写一个简单的日历
思路:先写一个结构和样式,然后写本月的时间,之后计算上下月份的关系 <!DOCTYPE html> <html lang="en"> <head> ...
随机推荐
- ILSpy 反编译.NET
ILSpy 是一个开源的.NET反编译工具,简洁强大易用是它的特征.在绝大多数情况下,它都能很好的完成你对未知程序集内部代码的探索.
- vc到vs2015消息函数
afx_msg LRESULT OnMyIconNotify(WPARAM wParam,LPARAM lParam); vc6 可以是void vs2015不可以 ON_MESSAGE(MYWM_ ...
- maven 无法下载私服jar包,如刚上传的第三方jar包无法下载。。
原因可能是: 在你下载该文件时 ,的确 私服上没有该文件. 但是maven会在本地仓库建立文件夹路径,并且今天不会再去私服下载. 即使你现在上传3rd jar ,也不会去下载,导致一直找不到jar.. ...
- sklearn中的分词函数countVectorizer()的改动--保留长度为1的字符串
1简述问题 使用countVectorizer()将文本向量化时发现,文本中长度唯一的字符串会被自动过滤掉,这对于我在做的情感分析来讲,一些表较重要的表达情感倾向的词汇被过滤掉,比如文本'没用的东西, ...
- 2018.10.13 bzoj1834: [ZJOI2010]network 网络扩容(最大流+费用流)
传送门 网络流水题啊. 第一问直接放心跑最大流(本来还以为有什么tricktricktrick). 第二问就直接把原来的边(u,v,c,w)(u,v,c,w)(u,v,c,w)变成(u,v,c,0)( ...
- IntelliJ IDEA 2017版 编译器使用学习笔记(一) (图文详尽版);IDE快捷键使用;IDE多行代码同时编写
IntellJ是一款强大的编译器,那么它有很多实用的功能 一.鼠标点击减少效率,快捷键实现各种跳转 (1)项目之间的跳转 快捷键位置: 操作:首先要有两个项目,然后,在不同窗口打开:如图: 然后使用快 ...
- 关于this对象
1.在全局函数中this指的是window 2.当函数被当做方法调用时,this等于那个对象 3.匿名函数具有全局性,只要是匿名函数,this指向window 实例1: var name = 'the ...
- file.write(str),file.writelines(sequence)
file.write(str)的参数是一个字符串,就是你要写入文件的内容.file.writelines(sequence)的参数是序列,比如列表,它会迭代帮你写入文件.
- not allowed to access to crontab because of pam configuration
如果运行crontab如遇下面这样的错误: $ crontab -l You (zhangsan) are not allowed to access to (crontab) because of ...
- autolayout之后获取uiview的frame
这个只要一行代码就搞定了.详细请看: In order to get the right frame/bounds of your UIImageView after resizing, you ne ...