“凡是能用JS 写出来的,最终都会用JS 写”,这是一个非常著名的定律,用在爬虫这里再合适不过了。

一说到爬虫很多人都会想到python,的确,python语法简洁,还有scrapy这一类强大的工具可以使用。

但是如果只是想写一个小爬虫,爬取论坛里的几张帖子,帖子里面的几个楼层,然后合成一篇文章。这点小数据量使用scrapy就有点杀鸡用牛刀了,而且还得设置一堆东西,非常麻烦,不够灵活。

而JavaScript就非常适合这一类小爬虫,首先是自带异步架构,能同时爬取多张网页内容,效率上来说比python高多了,我用两个语言写过爬取代理ip的爬虫,当JavaScript爬完时吓了我一跳,这速度快极了。

当然,python也可以通过开启多线程、多协程来实现同时爬取多张网页,但是这就比默认就异步的JavaScript麻烦多了。

所以,如果想简单、高效地写个小爬虫,非JavaScript莫属。

有多快多简单呢?现在就来写个豆瓣top250的爬虫,爬取10张网页,250部电影的名字、评分和封面地址;

1.如何安装

要通过js写爬虫,需要用到三个模块,request、cheerio和fs,其中fs内置了,只需要安装前两个即可,安装命令:

npm install request cheerio
复制代码

2.获取网页内容

request可以链接网页,爬取内容,这里我们只需要给它传递两个参数就行,一个为url(网址),另一个为回调函数; request会向回调函数传递三个参数,分别是error(错误信息),response(响应信息),body(网页内容):

var request = require('request')
var cheerio = require('cheerio')
var fs = require('fs')
var movies = []var requstMovie = function(url){request('https://movie.douban.com/top250',function(error, response, body)){//res.statusCode 为200则表示链接成功if(error === null && response.statusCode === 200){console.log('链接成功')//使用cheerio来解析body(网页内容),提取我们想要的信息var e = cheerio.load(body)//通过分析网页结构,我们发现豆瓣每部电影都通过item属性隔开var movieDiv = e('.item')//通过for循环来提取每部电影里的信息for (let i = 0; i < movieDiv.length; i++) {//takeMovie函数能提取电影名称、评分和封面let movieInfo = takeMovie(movieDiv[i])log('正在爬取' + movieInfo.name)//将提取到的电影放入数组movies.push(movieInfo)}}})
}
复制代码

3.提取电影信息

通过创建一个类来包含我们想要的属性,在每次调用takeMovie函数提取信息时都会初始化这个类,然后赋值给相应的属性; 之后放入movies数组里;

//电影的类
var movie = function(){this.id = 0this.name = ''this.score = 0this.pic = ''
}var takeMovie = function(div){var e = cheerio.load(div)//将类初始化var m = new movie()m.name = e('.title').text()m.score = e('.rating_num').text()var pic = e('.pic')//cheerio如果要提取某个属性的内容,可以通过attr()m.pic = pic.find('img').attr('src')m.id = pic.find('em').text()return m
}
复制代码

4.爬取所有top250

现在要爬取所有的top250信息,总共有10张网页,每张包含25部电影信息,创建一个函数来生成每张网页的网址,然后通过request进行爬取:

var top250Url = function(){let l = ['https://movie.douban.com/top250']var urlContinue = 'https://movie.douban.com/top250?start='let cont = 25for (let i = 0; i < 10; i++) {l.push(urlContinue+cont)cont += 25}return l
}//爬取所有网页
var __main = function(){var url = top250Url()for (let i = 0; i < url.length; i++) {requstMovie(url[i])}
}__main()
复制代码

5.异步架构的坑

当我们爬取完所有的网页后就会发现,movies里的电影信息并不按我们爬取的顺序,这也是异步架构一个需要注意的大坑; 在爬取第一张网页时,JavaScript不会等到处理结束才接着爬第二张,有时候各个网页返回的速度有所差异,会造成先爬取的不一定会先出结果,因此在电影排序上会出现混乱; 所以我们还需要对爬取下来的内容重新进行排序,然后保存:

//sortMovie回调函数能比较两个对象属性大小
var sortMovie = function(id){return function(obj ,obj1){var value = obj[id]var value1 = obj1[id]return value - value1}
}//保存文件
var saveMovie = function(movies){var path = 'movie.txt'var data = JSON.stringify(movies, null, 2)fs.appendFile(path, data, function(error){if(error == null){log('保存成功!')} else {log('保存失败',error)}})
}
复制代码

我们需要等到所有网页都爬取分析完才执行sortMovie和saveMovie函数,由于JavaScript是异步,即使这两个函数放在最底部也会在分析完之前执行; 一般会通过Promise来控制异步,但是为了方便,这里我们通过if来判断,在每次爬取网页后,都会判断movies里是否包含250条信息,如果有则说明全部爬取到了:

var requstMovie = function(url){request(url, function(error, response, body){if (error === null && response.statusCode === 200){var e = cheerio.load(body)var movieDiv = e('.item')for (let i = 0; i < movieDiv.length; i++) {let movieInfo = takeMovie(movieDiv[i])log('正在爬取' + movieInfo.name)movies.push(movieInfo)}//判断movies数量if (movies.length === 250){//通过sort将数组内每两个元素放入比较函数var sortM = movies.sort(sortMovie('id'))//保存文件saveMovie(sortM)}} else {log('爬取失败', error)}})}
复制代码

到这里,爬虫已经写完了,来运行一下:

完整代码可以通过github查看:DoubanMovies.JS

也可以访问我的网站,获取更多文章:Nothlu.com

Node.js可能是最适合写简易小爬虫的语言,速度极快、代码极少相关推荐

  1. node.js抓取数据(fake小爬虫)

    在node.js中,有了 cheerio 模块.request 模块,抓取特定URL页面的数据已经非常方便. 一个简单的就如下 var request = require('request'); va ...

  2. Node.js 淘票票院线电影爬虫

    Node.js 淘票票院线电影爬虫 环境 node.js v12.16.3 axios@0.20.0 cheerio@1.0.0-rc.3 npm安装 npm install axios cheeri ...

  3. node.js+uni计算机毕设项目基于小程序的农牧认养系统(程序+小程序+LW)

    该项目含有源码.文档.程序.数据库.配套开发软件.软件安装教程.欢迎交流 项目运行 环境配置: Node.js+ Vscode + Mysql5.7 + HBuilderX+Navicat11+Vue ...

  4. 【Nodejs篇五】Node js 使用 superagent 与 cheerio 完成简单爬虫

    目标 当在浏览器中访问 http://localhost:3000/ 时,输出 CNode(https://cnodejs.org/ ) 社区首页的所有帖子标题和链接,以 json 的形式. 输出示例 ...

  5. node.js调用ejs模板,在浏览器上打印出ejs模板内代码的解决方案

    2019独角兽企业重金招聘Python工程师标准>>> 今天遇到一个非常奇葩的问题,node.js调用ejs模板的时候,在浏览器端居然把此模板内的所有代码都打印出来了,当时我和我的小 ...

  6. python爬取大众点评数据_利用Node.js制作爬取大众点评的爬虫

    前言 Node.js天生支持并发,但是对于习惯了顺序编程的人,一开始会对Node.js不适应,比如,变量作用域是函数块式的(与C.Java不一样):for循环体({})内引用i的值实际上是循环结束之后 ...

  7. 用nodejs写一个简易小爬虫

    今天突然心血来潮,不如我用nodejs写一个小爬虫吧,nodejs说实话,自从它出生以来,就变成了前端的福音了,我也是一直想学,也曾经自己研究过一段时间,可是我没用到过项目上,爬虫也没写过,我就上网看 ...

  8. 小程序 node.js mysql_基于Node.js+MySQL开发的开源微信小程序B2C商城(页面高仿网易严选)...

    高仿网易严选的微信小程序商城(微信小程序客户端) 界面高仿网易严选商城(主要是2016年wap版) 测试数据采集自网易严选商城 功能和数据库参考ecshop 服务端api基于Node.js+Think ...

  9. 利用 node.js 云函数解密获取微信小程序的手机号码等加密信息 encryptedData 的内容。

    首先你必须会用微信小程序的云函数功能: 1.创建一个名为token的云函数 2.在云开发的云函数管理中添加对应的token云函数 3.在开发工具中编辑云函数token 4.点击右键,安装并部署 大致是 ...

最新文章

  1. 特征选择和特征生成问题初探
  2. 谷歌guava_Google Guava MultiMaps
  3. uva 10118 ——Free Candies
  4. Oracle数据到MaxCompute乱码问题详解
  5. docker启动停止操作命令
  6. Cron 触发器及相关内容 (第二部分)
  7. HDU1172 猜数字【暴力+进制】
  8. 如何改变图片大小-前端入门
  9. Hulu2022校招 | 笔试真题及解法揭秘
  10. python另存为对话框_python – 另存为文件对话框 – 如何不允许覆盖
  11. Android开发 - PsyDuck说明书
  12. Python——图像处理(crop()函数、thumbnail方法)
  13. 120名商家眼中微信营销的十个真相
  14. 局域网病毒入侵原理及防范方法
  15. linux下如何查看BIOS版本,在Ubuntu下查看BIOS资料
  16. iviewui-Table fixed状态下遮挡滚动条
  17. 智能公交站牌远程通信系统解决方案,公车信息一目了然
  18. python程序设计的选择题_智慧树知到Python程序设计基础选择题答案
  19. 阿里云副总裁杨名:“通向智能之路”
  20. 后台管理系统结构分析

热门文章

  1. linux中使用scp远程拷贝文件及文件夹
  2. [Java开发之路](23)装箱与拆箱
  3. 重复调用的代码块——方法
  4. GdiPlus[44]: IGPGraphics (三) 关于文本绘制续 - IGPStringFormat
  5. EXCEL公式、函数、图表应用技巧800问
  6. 在高并发分布式情况下生成唯一标识id
  7. httpclient get post
  8. Hadoop_27_MapReduce_运营商原始日志增强(自定义OutputFormat)
  9. 应用程序异常管理组件 Example 程序
  10. 数据导入报错:Got a packet bigger than‘max_allowed_packet’bytes的问题