浏览器抓取网页( Web应用程序更为迅捷地回应用户动作并避免了没有改变的信息)
优采云 发布时间: 2022-01-25 08:09浏览器抓取网页(
Web应用程序更为迅捷地回应用户动作并避免了没有改变的信息)
Ajax技术(属于前端技术)
那就是“异步 JavaScript 和 XML”,它与服务器交互而不刷新页面。
特点:异步请求,部分刷新
同步:发送方发送数据后,等待接收方发回响应,然后再发送下一个数据包;
异步:发送方发送数据后,不等待接收方回传响应,然后发送下一个数据包。
**好处:** Web 应用程序对用户操作的响应速度更快,避免通过网络发送未更改的信息,从而减少服务器压力。
**缺点:**浏览器实现的差异,需要处理兼容性问题;不利于SEO(SEO只能识别页面首次呈现的数据,不能异步);不能前后左右;默认不支持跨域访问。
**注意:**ajax 技术只能在网络协议环境中使用。不能直接将页面拖入浏览器执行。它必须以 Web 服务器模式访问。
AJAX编写步骤:
1.创建一个AJAX对象;
2.设置请求路径、请求方式等;
3.绑定*敏*感*词*状态变化的处理函数,可以在处理函数中获取响应数据(回调函数);
4.发送请求;
创建 ajax 对象时的浏览器兼容性处理
function createAjax() {
var ajax;
try { //非IE
ajax = new XMLHttpRequest(); //IE浏览器下没有XMLHttpRquest这个对象就会报错
} catch(e) {
ajax = new ActiveXObject('Microsoft.XMLHTTP');
}
return ajax;
}
响应处理和响应流
响应处理,即根据状态码和AJAX对象的状态信息,对服务响应浏览器的数据进行不同的处理,可以在绑定状态的处理函数中编写相应的逻辑代码改变。
AJAX 对象有 4 个属性:
readyState 一共有5个状态值,0-4,每个值代表不同的含义:onreadystatechange,一旦状态不标准,就会被执行,多次改变,多次执行
0:初始化,AJAX对象还没有初始化,new XMLHttpRequest();
1:加载,AJAX对象开始发送请求,ajax.open(请求方法,请求路径);
2:加载完成,发送AJAX对象的请求,ajax.send();
3:分析:AJAX对象开始读取服务器的响应,ajax.onreadystatechange;
4:完成,AJAX对象读取服务器响应并结束。
status 表示响应的 HTTP 状态码。常见的状态码如下:
200:成功;
302:重定向;
404:找不到资源;
500:服务器错误;
responseText 获取字符串形式的响应数据(常用)
responseXML 获取 XML 格式的响应数据
综上所述,状态变化的处理函数一般只针对ajax.readyState4和ajax.status200这两种情况进行处理(这也意味着我们什么时候可以开始渲染数据?服务器响应并成功获取数据后),然后根据后台返回的数据类型决定从responseText或responseXML中获取服务器响应返回的数据。
ajax 获取请求
let oBtn = document.getElementById("obtn");
let oDiv = document.getElementById("odiv");
oBtn.onclick = () => {
console.log("点击了按钮");
//发送ajax请求
//1.创建ajax对象
let ajax = new XMLHttpRequest();
//2.设置请求方式、请求路径url
ajax.open("GET", "/get_data");
//3.绑定*敏*感*词*状态的改变的处理函数,在这个函数里面可以获取响应数据(回调函数)
ajax.onreadystatechange = () => {
//这个函数里面的代码什么时候执行?状态发生改变的时候就执行
//获取响应的数据
//什么时候页面开始渲染数据?服务器响应完毕之后ajax.readyState为4,并且成功获取数据之后ajax.status为200
if(ajax.readyState === 4 && ajax.status === 200) {
//服务器传来的数据用什么表示?ajax.readyState
console.log(ajax.readyState);
//渲染数据到页面上
oDiv.innerHTML = ajax.responseText;
}
}
//发送请求
ajax.send();
}
服务器代码(在 nodejs 文档中解释)
const http = require("http");
const fs = require("fs");
const path = require("path");
const port = 8081;
const server = http.createServer((request, response) => {
//每来一个请求就执行一次这里的代码
//判断浏览器需要哪个资源文件,把下面这些代码进行封装的话就是路由
let reqUrl = request.url;
if(reqUrl === '/' || reqUrl === '/index.html') {
//读取页面内容,返回信息
let filePath = path.join(__dirname, "assets", "html", "index.html");
let content = fs.readFileSync(filePath);
response.end(content);
} else if(reqUrl === '/detail.html') {
//读取页面内容,返回信息
let filePath = path.join(__dirname, "assets", "html", "detail.html");
let content = fs.readFileSync(filePath);
response.end(content); //这句不能放在外面,因为使用let定义的content有块级作用域
} else if(reqUrl === '/get_data') { //或者正则:/get_data.*/.test(reqUrl)
response.end("接收到ajax的get请求,这是响应给浏览器的数据");
//上面的字符串就是响应到客户端的ajax.responseText
} else if(reqUrl.endsWith(".css")) {
//如果读取的是一个css文件,也是一个请求,也会执行一次代码
//哪些标签会造成请求?就有href(link)和src(src img)属性的标签,浏览器是自发的请求;还有像按钮、a标签的话需要在表单里而且需要点击过后才会请求
//如果用a标签实现跳转的话,index.html中跳转到详情页
//这里的跳转地址不是看前端的路径,而是看后端的路由是怎么配的,和这里的if else里的判断内容一致,点击之后也是一次请求
let filePath = path.join(__dirname, "assets", "css", "index.css");
let content = fs.readFileSync(filePath);
response.end(content);
} else {
response.setHeader("Content-type", "text/html; charset=utf-8"); //不加这句下面的语句会出现乱码
response.end("404错误:该资源找不到!");
}
})
server.listen(port, (error) => {
console.log(`WebServer is listening at port &{port}!`);
})
ajax 发布请求
附:根本没有提交行为,但是在某些浏览器中有提交行为
用户名:
密&emsp码:
let oBtn = document.getElementById("obtn");
let oDiv = document.getElementById("odiv");
oBtn.onclick = () => {
//post提交
//获取用户填写的数据
let username = document.getElementById("username").value;
let password = document.getElementById("password").value;
let params = { //这样的形式是将获取的值看着方便且容易处理,下面处理时还需要转换为服务器需要的JSON格式
username,
password
}
//Ajax提交(四个步骤)
let ajax = new XMLHttpRequest();
ajax.open("POST", "/login_post");
ajax.onreadystatechange = () => {
if(ajax.readyState === 4 && ajax.status === 200) {
//相当于成功后的回调函数,这里可以封装为一个函数,写在最外面,通过调用使用
//ajax.responseText是服务器传过来的字符串
oDiv.innerHTML = ajax.responseText;
}
}
ajax.send(JSON.stringify(params)); //服务器需要的是JSON格式的数据,所以需要转换一下
}
服务器代码
const http = require("http");
const fs = require("fs");
const path = require("path");
const port = 8081;
let uname = "laozhuang";
let pwd = "123456";
//包装为函数
function responseEnd(response, dirName, fileName) { //dirName文件路径,fileName文件名称
let filePath = path.join(__dirname, "assets", "dirName", "fileName");
let content = fs.readFileSync(filePath);
response.end(content);
}
const server = http.createServer((request, response) => {
let reqUrl = request.url;
if(reqUrl === '/' || reqUrl === '/index.html') {
responseEnd(response, "html", "index.html");
} else if(reqUrl === '/detail.html') {
responseEnd(response, "html", "detail.html");
} else if(reqUrl === '/login.html') {
responseEnd(response, "html", "login.html");
} else if(reqUrl === '/get_data') {
response.end("接收到ajax的get请求,这是响应给浏览器的数据");
} else if(reqUrl === '/login_post') {
//处理post请求
//一旦post请求过来就会触发data事件
request.on("data", (postData) => {
//postData就是post请求传递过来的参数,是Buffer对象,需要toString()一下
//还需要把JSON格式的字符串转换为对象,因为转为对象才能通过.的方式拿到属性值
//获取到浏览器传过来的数据,就是post请求传递过来的参数
let {username, password} = JSON.parse(postData.toString()); //解构
//需要查询数据库看有没有用户名,没有的话就需要注册,如果有还需对比密码是否正确,或者其他逻辑操作
if(username === uname && password === pwd) {
//还可以跳转之类的操作
response.end("登录成功!");
} else {
response.end("用户名或者密码错误,登录失败")
}
})
} else if(reqUrl.endsWith(".css")) {
responseEnd(response, "css", "index.css");
} else if(reqUrl.endsWith(".js")) {
responseEnd(response, "js", "index.js");
} else {
response.setHeader("Content-type", "text/html; charset=utf-8");
response.end("404错误:该资源找不到!");
}
})
server.listen(port, (error) => {
console.log(`WebServer is listening at port &{port}!`);
})
避免缓存问题:
AJAX 减少了重复数据的加载,提高了页面加载速度,因为数据会一直缓存在内存中,当提交的 URL 与历史 URL 一致时,就不需要提交给服务器了。虽然减轻了服务器的负载,提升了用户体验,但无法获取最新的数据。为了保证数据是最新的,需要禁用其缓存功能,主要有以下几种方式:
1.在 URL 中添加一个随机数:Math.random()
//客户端代码
ajax.open("GET", "/get_data" + Math.random());
//服务端代码
else if(reqUrl.startsWith('/get_data')) {
response.end("接收到ajax的get请求,这是响应给浏览器的数据");
//上面的字符串就是响应到客户端的ajax.responseText
}
2.给 URL 添加时间戳:new Date().getTime(),从 197 开始的毫秒数0.01.01
3.在使用 AJAX 发送请求之前添加 ajax.setRequestHeader("Cache-Control", "no-cache");
ajax.open(...);
ajax.setRequestHeader('Cache-Control', 'no-cache'); //请求头设置,在ajax.open()后面
ajax.send();
4. 在开发者工具下手动勾选 Network 的 Disable cache
超时处理:
有时网络有问题或者服务器有问题,导致请求时间过长。一般会提示网络请求稍后重试,以增加用户体验。代码可以通过定时器和请求中断来达到超时处理的效果。
var timer = setTimeout(() => {
//取消请求,终端请求
ajax.abort();
alert("请稍后重试")
}, time)
方法提取(不是最终形式,工作中不会这样写,懂的)
一个ajax请求、请求方法、请求路径、请求参数、获取服务器内容后的回调函数、时间等都可以封装成函数,这样get和post请求就可以写在一起了
function ajax(method, url, param, success, time) {
var ajax;
//处理ajax获取时候的兼容性问题
try { //非IE
ajax = new XMLHttpRequest();
} catch(e) { //IE
ajax = new ActiveXObject('Microsoft.XMLHTTP');
}
if(method === 'get') {
param = encodeURL(param); //针对get请求的查询参数出现中文的编码处理
url = url + '?' + param;
param = null;
}
ajax.open(method, url);
if(method === 'post') {
//请求体格式,例如name=nodejs&age=11
ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//也可以在标签中设设置
//...
}
ajax.onreadystatechange = function() {
if(ajax.readyState === 4 && ajax.status === 200) {
success(ajax.responseText); //在外面设置的获取服务端数据后处理数据的回调函数
}
}
ajax.send(param);
var time = setTimeout(() => {
ajax.abort();
}, time)
}
jQuery的ajax方法,get请求,post请求(没看过视频),指jQuery,指jQuery,指jQuery,.ajax就是jQuery.ajax