js 爬虫抓取网页数据(初始化中文文档搭建简单的服务器运行(图) )
优采云 发布时间: 2021-11-09 23:05js 爬虫抓取网页数据(初始化中文文档搭建简单的服务器运行(图)
)
初始化和安装依赖
npm init --yes
npm i express superagent cheerio -s
复制代码
superAgent 是一个轻量级的 Ajax API。服务器端(Node.js)和客户端(浏览器端)都可以使用SuperAgent中文文档
Cheerio 是一个快速、灵活、可实现的 jQuery 核心实现,专门为服务器定制。Cheerio 中文文档
搭建一个简单的服务器
// 创建服务器实例
const express = require('express')
const app = express()
app.get('/', (req,res)=> {
res.send('爬虫实战')
})
// 获取服务器信息并打印
let server = app.listen(3000, () => {
let host = server.address().address;
let port = server.address().port;
// %s 另一种拼接字符串方法
console.log('程序已运行 http://%s:%s', host, port);
})
复制代码
运行服务器
nodemon index.js
复制代码
浏览器输入 localhost:3000
分析页面内容
百度新闻-海量中文信息平台 ()
示例,打开百度新闻首页、控制台、评论元素
使用cheerio获取id> ul> li> a 获取a标签中的文本
获取页面
引入superagent模块,调用get方法,传入页面地址
const superagent = require('superagent')
superagent.get('http://news.baidu.com/').end((err,res) => {
if(err) {
console.log('热点新闻抓取失败' + err);
}
console.log(res);
})
复制代码
保存后更新服务器,终端打印结果。由于内容太多,终端无法容纳,上半部分已被覆盖。
页面地址返回的所有数据都会收录在res中
数据处理
接下来开始处理这些数据
下面介绍cheerio库,声明res的处理函数。上面,声明需要返回的结果。superagent.get() 调用处理函数中的方法并将结果返回给之前声明的变量
这里需要注意请求方法app.get('/', (req,res)=> {})要放在处理函数下
const express = require('express')
const superagent = require('superagent')
const cheerio = require('cheerio')
const app = express()
let hotNews = []
superagent.get('http://news.baidu.com/').end((err,res) => {
if(err) {
console.log('热点新闻抓取失败' + err);
}
// 调用函数,返回的结果直接赋值给外部变量
hotNews = getHotNews(res)
})
let getHotNews = res => {
// 通过 cheerio库的load方法传入res.text (获取res的全部字符串) 得到 $
let $ = cheerio.load(res.text)
// 对$方法传入选择器选择元素,得到的是一个
// $('#pane-news ul li a')
console.log($('#pane-news ul li a'));
}
app.get('/', (req,res)=> {
res.send(hotNews)
})
// 获取服务器信息并打印
let server = app.listen(3000, () => {
let host = server.address().address;
let port = server.address().port;
// %s 另一种拼接字符串方法
console.log('程序已运行 http://%s:%s', host, port);
})
复制代码
$('#pane-news ul li a') 返回一个收录所有对应节点对象的数组
let getHotNews = res => {
// 声明空数组
let hotNews = []
// 通过 cheerio库的load方法传入res.text (获取res的全部字符串) 得到 $
let $ = cheerio.load(res.text)
// 对$方法传入选择器选择元素,得到一个包含所有对应元素的数组
// 对数组进行遍历,获取每个元素内的 text 和 href 放入 news 对象
$('#pane-news ul li a').each((index, ele) => {
let news = {
title: $(ele).text(), // 获取新闻标题
href: $(ele).attr('href') // 获取新闻页面链接
}
hotNews.push(news) // 每次遍历的结果 把news推入事先声明的数组
})
// 遍历结束将结果返回出去,通过调用将结果赋值给最上方的空对象
return hotNews
}
复制代码
返回数据
函数调用后打印结果
传递的值改为返回值
app.get('/', (req,res)=> {
res.send(hotNews)
})
复制代码
当然,获取到数据后,可能不是从客户端直接显示出来的
这部分可以在superagent下处理
superagent.get('http://news.baidu.com/').end((err,res) => {
if(err) {
console.log('热点新闻抓取失败' + err);
}
// 调用函数,返回的结果直接赋值给外部变量
hotNews = getHotNews(res)
/*
1.存入数据库
2.跳转到对应的路由,显示数据页面 /echarts
3.路由页面请求数据库中的数据,显示到echarts图表中
*/
})
复制代码
本地新闻抓取失败的原因
因为代码是一遍遍写的,这里就不写了。之所以无法获取到这部分内容,是因为这部分数据是在浏览器当前页面发起请求动态获取的。
你通过superagent访问得到的是这个域名下的所有静态内容,不能触发功能请求完成动态内容的加载。
解决方法是使用第三方插件模拟浏览器访问百度新闻首页。在这个模拟浏览器中,当动态内容加载成功时,抓取数据返回给前端浏览器
噩梦实现动态数据采集
segmentio/nightmare:一个高级浏览器自动化库。()
使用噩梦般的自动化测试工具
Electron 可以使用纯 javascript 调用 Chrome 丰富的原生接口来创建桌面应用程序。它可以被看作是一个专注于桌面应用程序的 node.js 变体,而不是一个 web 服务器。其基于浏览器的应用方式可以非常方便的进行各种响应式交互
nightmare 是一个基于电子的自动化网页测试和爬虫框架,因为它具有和plantomJS一样的自动化测试功能,可以模拟用户在页面上的行为来触发一些异步数据加载,也可以像下面这样直接访问URL请求库。抓取数据,并且可以设置页面的延迟时间,所以无论是手动触发脚本还是行为触发脚本都很容易
安装依赖
npm i nightmare -s
复制代码
用
引入模块,获取实例,调用方法动态获取数据
const express = require('express')
const app = express()
const Nightmare = require('nightmare')
// 设置 show: true 会显示一个自动化的内置浏览器
const nightmare = Nightmare({ show: true})
const cheerio = require('cheerio')
let localNews = []
//---------------------------------------------------------------------------------
nightmare
.goto('http://news.baidu.com')// 需要访问的链接
.wait('div#local_news') //等待加载的节点
.evaluate(() => document.querySelector('div#local_news').innerHTML)// 评估节点内容
.then(htmlStr => { //获取到html字符串
localNews = getLocalNews(htmlStr) // 调用方法
})
.catch(err => {
console.error(err)
})
//----------------------------------------------------------------------------------
let getLocalNews = htmlStr => {
let localNews = []
let $ = cheerio.load(htmlStr) // 这里因为获取到的已经是字符串了,不需要.text
$('ul#localnews-focus li a').each((index, ele) => {
let news = {
title: $(ele).text(),
href: $(ele).attr('href')
}
localNews.push(news)
})
return localNews
}
app.get('/', (req,res)=> {
res.send(localNews)
})
// 获取服务器信息并打印
let server = app.listen(3000, () => {
let host = server.address().address;
let port = server.address().port;
// %s 另一种拼接字符串方法
console.log('程序已运行 http://%s:%s', host, port);
})
复制代码
现在打开链接,可以看到动态加载的内容