前端爬数据当接口 你还在一个一个的写json数据吗?详细教学
会用node进行爬数据吗?
爬数据之前先浅聊一下Node.js
Node.js 是一个开源和跨平台的 JavaScript 运行时环境。 Node.js 在浏览器之外运行 V8 JavaScript 引擎(Google Chrome 的内核)。Node.js 应用程序在单个进程中运行,无需为每个请求创建新的线程。 Node.js 在其标准库中提供了一组异步的 I/O 原语,以防止 JavaScript 代码阻塞,通常,Node.js 中的库是使用非阻塞范式编写的,使得阻塞行为成为异常而不是常态。当 Node.js 执行 I/O 操作时(比如从网络读取、访问数据库或文件系统),Node.js 将在响应返回时恢复操作(而不是阻塞线程和浪费 CPU 周期等待)。
别急,再谈一下爬虫
网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定规则,自动的抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
在生活中网络爬虫经常出现,搜索引擎就离不开网络爬虫。例如,百度搜索引擎的爬虫名字叫作百度蜘蛛(Baiduspider)。百度蜘蛛,是百度搜索引擎的一个自动程序。它每天都会在海量的互联网信息中进行爬取,收集并整理互联网上的网页、图片视频等信息。当用户在百度搜索引擎中输入对应的关键词时,百度将从收集的网络信息中找出相关的内容,按照一定的顺序将信息展现给用户。
开启实战,爬豆瓣网的数据
前端爬数据主要是通过爬取请求地址网页的html,然后将html进行解析,拿取我们的需要的数据的节点。
平常大家都是看到python爬虫,搞个请求头,模拟用户进行爬数据。
在node里,有个属于前端人的高科技,cheerio
cheerio:
cheerio是jquery核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对DOM进行操作的地方。 大家可以简单的理解为用来解析html非常方便的工具。
cheerio
你可以使用该cheerio.load
方法加载标记。该方法将标记作为参数。它还需要另外两个可选参数。如果你有兴趣,可以在文档中阅读有关它们的更多信息。
Cheerio 和 Web 浏览器之间的主要区别在于,cheerio 不生成视觉渲染、加载 CSS、加载外部资源或执行 JavaScript。它只是解析标记并提供用于操作生成的数据结构的 API。
我们在使用之前只需要在终端安装即可 npm i cheerio。不过在这之前,更重要的是拿到请求的url的数据。如果你想使用cheerio 来抓取网页,您需要首先使用axios或node-fetch等包来获取标记。我这里使用request-promise,它是服务端发起请求的工具包
爬到了数据我们肯定要把它存起来,这里我采用了fs
写入文件最简单的方式是使用fs.writeFile() API
详情看node 官方 Node.js
这是官方文档
const fs = require('fs')
const content = '一些内容'
fs.writeFile('/Users/joe/test.txt', content, err => {
if (err) {
console.error(err)
return
}
//文件写入成功。
正式开启爬数据的教程
1. 首先我们先初始化项目
利用npm init -y初始化项目,然后可以之后安装的依赖都放到这里。
npm init -y
2. 然后安装好我们之后所需要的依赖
安装好我们所要的依赖
npm i request-promise
npm i cheerio
3. 准备好所有引入
let request = require('request-promise')
let fs = require('fs') // 后端 操作系统 I/O 网络 硬件 前端 浏览器
const cheerio = require('cheerio')
let url = 'https://movie.douban.com/top250'
4. 请求数据
在这里我把所有东西都放在了main这个函数里。
同时在这里我定义了一个空数组 存取电影信息。
let movies = []
const main = async () => {
let html = await request({
url
})
}
5. 在Cheerio 中加载标记
我们传递第一个也是唯一需要的参数,并将返回值存储在$
变量中。我们使用该变量是因为cheerio 与Jquery$的相似性。如果你愿意,可以使用不同的变量名。
let $ = cheerio.load(html) // 内存中构造一个DOM树 VDOM
6.在 Cheerio 中选择元素
Cheerio 支持大多数常见的 CSS 选择器,例如class
、id
和element
选择器等。在下面的代码中,我们选择元素#content .article .grid_view
然后将所选元素记录到控制台。
我们要拿的数据就在这个item里,利用find找到所有#content .article .grid_view
下的item。
let movieNodes = $('#content .article .grid_view').find('.item')
7. 开始拿取数据
for 循环 遍历 movieNodes 拿到每一个 item
for (let movieNode of movieNodes) {
// 将item 设置为加载标记
let $ = cheerio.load(movieNode)
// 拿取 item 下的 info hd 下的 所有sapn
let titles = $('.info .hd span ')
// titles 不一定为数组,可能是类数组 无法调用map 用call 强制this
titles = [].map.call(titles, t => {
// 调用jQuery 里的方法text 拿取文字
// 同时调用正则表达式去掉换行和空格
return $(t).text().replace(/[ ]|[\r\n]/g,"")
})
// console.log(titles);
// 拿取 item 下的 info 的bd 元素
let bd = $('.info .bd')
// 拿取 item 下的 info 的bd 里的 p 中的文字
let info = bd.find('p').text().replace(/[ ]|[\r\n]/g,"")
// 拿取 .star下 .rating_num 中的评分文字
let score = bd.find('.star .rating_num').text()
if (titles.length)
// 将数据存取到 movies数组里
movies.push(({titles, info, score}))
}
8. 将数据存放起来
-
利用fs.writeFile方法将movies 中的数据存放起来 自动在根目录下生成一个
output.json
文件。 -
利用
JSON.stringify
将movies格式化一下满足json文档。 -
utf-8
确保汉字能够显示不会乱码
fs.writeFile('./output.json', JSON.stringify(movies), 'utf-8', () => {
console.log('生成json文件成功');
})
9. 效果展示
[
{
"titles": [
"肖申克的救赎",
" / The Shawshank Redemption",
" / 月黑高飞(港) / 刺激1995(台)",
"[可播放]"
],
"info": "导演:弗兰克·德拉邦特FrankDarabont 主演:蒂姆·罗宾斯TimRobbins/...1994 / 美国 / 犯罪剧情希望让人自由。",
"score": "9.7"
},
{
"titles": [
"霸王别姬",
" / 再见,我的妾 / Farewell My Concubine",
"[可播放]"
],
"info": "导演:陈凯歌KaigeChen 主演:张国荣LeslieCheung/张丰毅FengyiZha...1993 / 中国大陆中国香港 / 剧情爱情同性风华绝代。",
"score": "9.6"
},
},
....
]
10. app.js完整代码
let request = require('request-promise')
let fs = require('fs') // 后端 操作系统 I/O 网络 硬件 前端 浏览器
const cheerio = require('cheerio')
let url = 'https://movie.douban.com/top250'
let movies = []
const main = async () => {
let html = await request({
url
})
// console.log(html);
let $ = cheerio.load(html) // 内存中构造一个DOM树 VDOM
let movieNodes = $('#content .article .grid_view').find('.item')
// console.log(movieNodes);
for (let movieNode of movieNodes) {
let $ = cheerio.load(movieNode)
let titles = $('.info .hd span ')
// console.log(Object.prototype.toString.call(titles));
// titles 不为数组 无法调用 map 用call
titles = [].map.call(titles, t => {
return $(t).text()
})
// console.log(titles);
let bd = $('.info .bd')
let info = bd.find('p').text().replace(/[ ]|[\r\n]/g,"")
let score = bd.find('.star .rating_num').text()
if (titles.length)
movies.push(({titles, info, score}))
}
// console.log(movies);
fs.writeFile('./output.json', JSON.stringify(movies), 'utf-8', () => {
console.log('生成json文件成功');
})
}
main()
转载自:https://juejin.cn/post/7212210588826730552