1. http爬虫 + http web服务器渲染数据发送前台 + 中文乱码
```
http模块
数据请求
get
request
post
案例: 后端爬虫
名词解释:
爬虫: 爬去数据
流程:
后端数据请求 ---》 数据分析 ---》数据清洗 ----》 数据前台发送
爬虫: 并不是所有网站都能爬取的
反爬虫
options 就是一个对象,也是一个配置
const http = require( 'http' )
const cheerio = require( 'cheerio' )
// http://jx.1000phone.net/teacher.php/Class/classDetail/param/rqiWlsefmajGmqJhXXWhl3ZiY2dn
const options = {
hostname: 'jx.1000phone.net',
port: 80,
path: '/teacher.php/Class/classDetail/param/rqiWlsefmajGmqJhXXWhl3ZiY2dn',
method: 'GET',
headers: {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Cookie': 'PHPSESSID=ST-91625-drj9QJxH287RYSrtXEIOz7ZePTo-izm5ejd5j1npj2pjc7i3v4z',
'Host': 'jx.1000phone.net',
'Pragma': 'no-cache',
'Referer': 'http://jx.1000phone.net/teacher.php/Class/index',
'Upgrade-Insecure-Requests': 1,
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': ''
}
};
const req = http.get( options , (res) => { // res response 响应( 回馈 )
// // 错误判断 判断状态码 判断数据类型
// const { statusCode } = res;
// const contentType = res.headers['content-type'];
// let error;
// if (statusCode !== 200) {
// error = new Error('Request Failed.\n' +
// `Status Code: ${statusCode}`);
// } else if (!/^application\/json/.test(contentType)) {
// error = new Error('Invalid content-type.\n' +
// `Expected application/json but received ${contentType}`);
// }
// if (error) {
// console.error(error.message);
// // consume response data to free up memory
// res.resume();
// return;
// }
res.setEncoding('utf8'); // 得到结果的编码
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
try {
// console.log( rawData ) // html string
const $ = cheerio.load( rawData )
$('td.student a').each( function ( i, ele) {
console.log( $(this).text() )
})
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
req.end()
/*
服务器:
可以运行在服务端一个网站(站点)
种类:
1. web服务器( 静态服务器 ) ,可以运行在浏览器中的服务器
2. api服务器 ( 后端接口 ) 后端语言暴露一个数据接口,用于前端数据请求( ajax fetch )
Node.js中原生创建web服务器
http模块
createServer( callback ) 创建服务器
callback中接收三个参数 request response
listen(port,host,callback) 监听服务器( 反馈服务器状态 )
port 端口
host 域名
名词: chunk 分片
我们刚才发送了一个html给前台,那么这种渲染数据的形式我们称之为: ‘后端渲染’,也称之为:‘服务端渲染’,英文叫法: ‘ssr’
*/
// 1. 引入http模块(对象)
const http = require('http')
// 2. 通过http模块身上的 createServer 这个api可以创建一个web服务器
// 3. 创建服务器端口和域名
const port = 8000
const host = 'localhost' // 127.0.0.1
const server = http.createServer((request, response) => {
response.writeHead(200, {
// 'Content-Type': 'text/html ;charset=UTF8',
'Content-Type': 'text/html'
})
response.write('<meta charset="UTF-8">')
const str = '<h3>hello Node.js server 你好吗</h3>'
response.write(str.toString()) //像前台发送数据( 信息 )
response.end() // 发送已经结束
}).listen(port, host, () => {
console.log(`The server running at:http://${ host }:${ port }`)
})
Node.js中中文乱码
1. 设置请求头
response.writeHead( 200, {
'Content-Type': 'text/html;charset=UTF8' // 小写也可以 utf8
})
2. 发送一个meta标签
response.write('<meta charset="UTF-8">')
3. toString() 在当前应用场景中还不行
二进制有效
将二进制 --- 》 string
```
-
前端模块化
问题: 为什么前端要使用模块化?
模块化: 是具有特定功能的一个对象( 广义理解 )
模块定义的流程:
1.定义模块(对象)
2.导出模块
3.引用模块
好处:
1. 可以存储多个独立的功能块 2. 复用性高
-
种类
- AMD( require.js)
- CMD ( sea.js )
- Common.js
-
AMD定义一个模块
define
// AMD /* 目录 admDir a.js index.js */ // AMD定义 a.js define ({ a: 1, b: 2, add: function(){} }) // AMD引用 index.js require([./a.js],function( moduleA ){ //moduleA指的就是定义来的对象 })
-
CMD定义模块
define
//CMD /* 目录结构 b.js index.js */ // 模块定义 b.js define(function(require, exports, module) { // 模块代码 }); //模块引用 index.js require('./b.js',function( moduleB ){ //moduleB就是b模块中导出的内容 })
面试题之一: CMD AMD 黄金
-
Common.js
Node.js使用了Common.js的规范( 必会的 王者 )
易错的理解:
common.js是属于node的 ×
node属于common.js ×
//common.js /* 目录结构: name.js index.js */ //模块的定义 name.js const nameObj = { name: 'Gabriel Yan ' } //模块的导出 name.js module.exports = nameObj //模块的引用 const nameObj = require('./name.js')
Node.js中Common.js规范的使用有三种类型:
-
内置模块( 内置模块指的是挂载在Node.js全局对象身上的api )
-
自定义模块
-
模块的定义
//举例 const student = { id: 1, name: 'Gabriel Yan' } const fn = function(){}
-
模块的导出
// 第一种导出 module.exports = student // 安全性不高 默认导出一个 //第二种导出 module.exports = { //批量导出,按需引用 student,fn }
-
模块的引用
// 这种引用对应第一种导出 const student = require('./xxx.js') // 这种引用对应第二种导出 const { student , fn } = require( './xxx.js ' )
注意:
在自定义模块引用时,require一定要写好路径
-
-
第三方模块
1. 别人已经封装好的模块 2. 这个模块具备一些特定的功能 3. 这些模块存放在 www.npmjs.com 这个网站中 这些模块的文档也记录在内 格式: var/let/const 变量名 = require( 模块名称 ) 总结: 第一步,使用npm/cnpm 安装 第二部,在文件中引入 第三部,在www.npmjs.com这个网站中找到这个模块的文档,根据文档来使用
思考: 我们是不是能将自己封装的自定义模块变成第三方模块?
分析:
第三方模块具备的特性:
1. 有一定的功能
2. 存储在: http://www.npmjs.com 中
解决: 自定义模块的上传( http://www.npmjs.com )
-
创建package.json文件
$ npm init -y
-
在http://www.npmjs.com 这个网站注册一个账号
注意:第一次登陆会发送一个邮件给你的邮箱( 这个发送是手动的 ),然后大家登陆邮箱激活
-
检查你的电脑的源是不是npm源
$ nrm ls
如果是,就不会理会
如果不是,那么切换到npm源
-
命令行登录npmjs仓库
$ npm adduser
-
创建模块并导出模块
-
查看你的包名称是否已经被使用
-
发布包
$ npm publish
一般的犯错点:
-
邮箱没有激活 ( 最多的 )
- npm源没有切换
- 整个电脑的npm就不能使用
如果以上方法没有解决:
你使用别人的账号去试一下就可以了
-D === --save-dev
//举例
cnpm i jquery -D === cnpm i jquery --save-dev // 开发环境下使用
cnpm i jquery -S === cnpm i jquery --save // 生产环境下使用
Node.js跨域
跨域;
前端跨域
jsonp
反向代理( 创建一个虚拟后端服务器,让这个后端服务器帮助我们请求数据)
后端跨域
node php java
-
设置请求头
-
使用第三方的中间件( cors )
中间件: 就是具有一定功能的一个函数