前言
最近几天,我很喜欢的歌手要举办演唱会了,霎时间网上一片热火朝天,各种话题都指向该如何抢票,接踵而来的各种“抢票攻略”…于是乎,我也开始“忧心忡忡”,担心自己抢不到票(其实根本不用担心,抢不到票是必然,毕竟咱也“些微”舍不得马内)。然后就找了几个后端的好朋友,想着他们能不能发挥一下特长和乐于助人的精神(不要误会,就是很纯粹的磨练一下他们的技术~ 好歹咱也是沐浴在春风里,生长在国旗下的社会主义好青年!),在被多方“谢邀”之后,他们建议我自己写…果然,万丈高楼平地起,成功还要靠自己!但是毕竟咱之前也没写过脚本,听说他们前两天“狗狗祟祟”地在研究如何获取csdn文章链接并进行访问,据说是比较好实现的,正好我也好奇前端如何爬取数据,就学习了“海量的”文章,拾起我零碎的知识。不好意思,话多了,详情如下:
安装配置
//初始化
npm init -y
//安装cheerio
npm install request cheerio -save
知识梳理
1、具体的实现思路:前端从地址栏拿到个人主页的链接之后,传递给后端,通过cheerio解析主页代码标签,拿到a标签中的链接,然后将所有的链接存放在数组中返回给前端,前端通过页面刷新,随机获取链接嵌入iframe标签中,实现不同文章页面的跳转访问。
2、前端向后端发送请求传递参数时:
若对象的参数或数组的元素中遇到地址,地址中包括?、&这些特殊符号时,对象/数组先要通过JSON.stringify转化为字符串再通过encodeURIComponent编码,接收时,先通过decodeURIComponent解码再通过JSON.parse转换为JSON格式的对象/数组。
3、jQuery知识:
- 当
DOM
(文档对象模型) 已经加载,并且页面(包括图像)已经完全呈现时,会发生 ready 事件。ready()
函数规定当ready
事件发生时执行的代码。 jQuery 事件 - ready() 方法 attr()
方法设置或返回被选元素的属性值。 jQuery 属性操作 - attr() 方法
4、nodeJS知识:
- 请求跨域:
res.header('Access-Control-Allow-Origin', '*');
- 数据流格式转换
- 使用
cheerio
来解析html
标签,cheerio
是nodejs
特别为服务端定制的,能够快速灵活的对JQuery
核心进行实现,工作于DOM
模型上,并且解析、操作、呈送都很高效。 Node.js使用cheerio解析html
代码展示
以下只作代码展示,详情可见注释。
nodeJS部分:
const https = require("https")
const cheerio = require("cheerio")
const express = require("express");
const app = express();
app.all('/csdnsrc', function (req, res, next) {
// 设置请求头为允许跨域
res.header('Access-Control-Allow-Origin', '*');
// // 接收时,先通过decodeURIComponent解码再通过JSON.parse转换为JSON格式的对象/数组
httpsGet(JSON.parse(req.query.name))
// 给前端返回数据
res.send(resurl)
});
// 定义一个数组,用于接收返回的个人文章链接
let resurl = []
function httpsGet(url) {
let src = 'https://blog.csdn.net/' + url
https.get(src, res => {
console.log("res.statusCode:", res.statusCode);
let data = "";
//'data' 事件:https://nodejs.cn/api/stream/event_data.html
// 当服务端接收到数据时触发
// 数据以流的形式传送过来,我们要将数据装为我们平时看到的形式,同时将多个段拼接起来,这两个工作,可以直接由拼接字符串来完成。
res.on("data", (chunk) => {
data += chunk;
})
// 当数据接收完毕时调用
res.on("end", () => {
// 使用cheerio来解析html标签
let $ = cheerio.load(data);
$(".main .user-profile-body .mainContent div .blog-list-box a").each(function () {
// attr() 方法设置或返回被选元素的属性值。
let blogUrl = $(this).attr("href");
resurl.push(blogUrl)
})
})
}).on("error", (err) => {
console.log(err.message);
})
}
app.listen(5000, (err) => {
if (!err) console.log('服务器启动了,请求信息地址为:http://localhost:5000/csdnsrc');
})
html部分:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 设置http-equiv="refresh" 网页每隔60s刷新一次 -->
<meta http-equiv="refresh" content="60">
<title>Document</title>
</head>
<body>
<!-- 在当前页面嵌入一个HTML页面 -->
<iframe id="csdn" width="100%" height="800px"></iframe>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
// 若对象的参数或数组的元素中遇到地址,地址中包括?、&这些特殊符号时,对象/数组先要通过JSON.stringify转化为字符串再通过encodeURIComponent编码,
// 接收时,先通过decodeURIComponent解码再通过JSON.parse转换为JSON格式的对象/数组
let data = JSON.stringify('csdn用户名')
let csdnsrc = []
fetch(`http://localhost:5000/csdnsrc?name=${data}`)
.then(res => res.json())
.then(res => {
csdnsrc = res;
// 随机生成一个数(要求:该数在返回数组的长度范围内)作为数组的下标
var index = Math.floor((Math.random() * csdnsrc.length));
// 当 DOM(文档对象模型) 已经加载,并且页面(包括图像)已经完全呈现时,会发生 ready 事件。
// ready() 函数规定当 ready 事件发生时执行的代码。
$(document).ready(function () {
// attr():给id为csdn的标签添加src属性
$('#csdn').attr('src', csdnsrc[index]);
})
})
</script>
</body>
</html>
以上是我学习到的成果!如有更好的方法,建议分享,共同进步!