|
" O3 f! R. E2 R0 `6 ` Koa -- 基于 Node.js 平台的下一代 web 开发框架 ! b/ [7 u; W2 S' \: c9 H" [3 y
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 4 i0 Q0 w* i% G$ [$ b4 d j
英文官网:http://koajs.com
u' h) S; [; O9 ~1 y 中文官网:http://koajs.cn 5 G& S# g) f" c* C6 c
1.koa
' S6 S4 H6 g" T, |( V; h: i+ g 安装koa包: npm i -S koa@latest
9 T0 f7 ^% l( `7 N# a- Q7 y 引入: const koa = require("koa"); 实例化对象: const app = new koa;
+ H/ v# r/ o% q# M. ?# m 通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 9 o: n8 U/ ^6 Q
use()函数中必须使用异步 async; use可是调用无数次;
" T' ]# U1 j! ^1 O 其中有两个参数: 5 F* L/ D% G, H9 |+ z: K! [
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 5 J7 f! z- k' p
b)next: next(),将本次控制权交给下一个中间件。
8 I; ` x: i; _5 |: B 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 7 }3 @9 m1 {* J _1 U4 l
1. next参数的使用demo # ?: W4 {4 P x0 n4 N- V* z$ d
`const Koa = require(``"koa"``);`3 e4 L. h% q2 e; Y5 y
`const koa =` `new` `Koa();`$ O8 D& _2 u, s% Z% d0 M
`//中间件1`
" l2 I9 E2 D2 O2 k `koa.use(async (ctx, next) => {`: ^; k, q- |. B8 X+ d1 ?: X
`console.log(``"1 , 接收请求控制权"``);`% L6 ^! D' p9 Q( T$ [
`await next();` `//将控制权传给下一个中间件`
* B, m5 b) Z. S$ ?, s0 D `console.log(``"1 , 返回请求控制权"``);`8 ^* Z; J6 _7 `& {3 Z4 {$ e3 U
`});` `//将中间件注册到koa的实例上`! G( k( X( R8 @" c3 m
`//中间件2`
6 B: {% _. F* B `koa.use(async (ctx, next) => {`
: i% I5 h1 t3 a% j- H4 B7 ]5 F5 ~ `console.log(``"2 , 接收请求控制权"``);`
& j; Q9 K- \) y& c- D await next();`
6 ?' G5 W' I1 E `console.log(``"2 , 返回请求控制权"``);`
; R* ~% X; A( z+ g `});`
9 R' @8 F# e5 s0 L `//中间件3`
/ S7 K y) N+ L5 X+ @7 `( K `koa.use(async (ctx, next) => {`) ^, f: c0 }6 E) I# m
`console.log(``"3 , 接收请求控制权"``);`
8 _( p. |2 M7 |. V `console.log(``"3 ,返回请求控制权"``);`
0 P% M# o; v: a `});`
3 y& a' l; E+ F `koa.listen(3000, ()=>{`- S" w9 z1 R2 |+ a
`console.log(``"开始监听3000端口"``);`& W p. Q/ y! o+ ?' V0 D7 f3 R, e
`});`
3 d. V) ?' O7 Z" Z; W7 p9 {. s 注:当中间件中没有next(),不会执行下面的中间件
- t- |! a% l5 R* Q a+ S1 B 访问localhost:3000的效果图;
: r) J3 q# s) y. D ; U% a8 W1 M/ ~: H1 b4 L2 g" ?
注:会有两次操作是因为图标icon也会请求一次 ) F& [3 F% |* S* N
2.ctx参数的使用demo , R$ Z) `6 X) t; C+ a e
`const Koa = require(``"koa"``);`# M9 w0 z5 V4 m* b
`const koa =` `new` `Koa();`
8 C0 b. a! [/ c `koa.use(async (ctx, next)=>{`
7 c2 W. U. c; m5 o `ctx.body =` `"body可以返回数据,"``;`
! ^) t7 ~ P- E& s0 Z; R1 c `ctx.body +=` `"可以多次调用,"``;`; H3 ?; n6 v. U, q7 G
`ctx.body +=` `"不需要end()"``;`1 I" [6 h2 l+ T! W( o0 ?" r
`});`
1 d* U6 \2 J; K0 B. y# g `koa.listen(3000, ()=>{`
6 }+ B0 ^' n* q1 ]! `; M7 w `console.log(``"监听开始"``);`. o1 S* Q6 B# {+ z7 U% W
`});` ! P) o% m& f' s6 m
效果: + ?7 T W; X+ \( _& j
5 E1 B. O, V: c) d; s' j ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
4 ~% N1 j6 g% H% |. I `const Koa = require(``"koa"``);`
. G1 Y1 D$ ~$ K/ X7 Q8 P: W `const koa =` `new` `Koa();`3 E$ e' `2 q( L! F$ T, z& Y! t
`koa.use(async (ctx, next)=>{`
% F c1 N- k" I7 B5 S& G `ctx.body = ctx.url;`
( n) q6 c9 D5 H `ctx.body = ctx.path;`
3 q9 p6 }2 ~+ F' t; T) l `ctx.body = ctx.query;`1 H( {) m* S+ r
`ctx.body = ctx.querystring;`
& k3 ~. @% O5 z `});`
% B: }/ w: J3 g3 [, L `koa.listen(3000, ()=>{`8 v% F; j* @: y; _
`console.log(``"监听开始"``);`
7 Z8 g7 m9 A2 _. |: O& [( ^ `});` 3 ]5 T1 V: A* B
访问http://localhost:3000/path?name=sjl&age=18为例,效果图: 3 A) d6 F7 F# I k c
1. url: 整个路径 6 |' z, Q7 @7 z; }
. W3 [& ~; e- g) w0 Z& l& @ 2. path: 非查询部分
4 E C) s' \7 @7 x1 u- T
( o+ N3 V5 l) n 3. query: 将查询部分转为JSON对象 0 Z3 {3 i- w2 ]/ P1 ` \
4 |! W; y) S4 b0 n9 c, @0 L% x: c
4. querystring: 将查询部分转为字符串 ) p6 d* O9 M6 ]2 I/ g. t- E
e2 h2 F) n/ z 5. ctx.state ,ctx.type 表示状态吗和类型
0 W* K7 i/ d8 A( v7 r$ ^! W* [ 2.简单爬虫练习
$ g' }' v5 P6 w0 _ G3 D4 j1 F! J L 安装request,cheerio模块 ) l3 C: b# A9 C7 y5 k6 I6 T& P& q
`npm i -S request: 请求模块`
3 S; P4 z, s5 l+ c: P/ `2 E' A1 n `npm i -S cheerio: 抓取页面模块(JQ核心)` ( J% U- a6 P% F2 \
抓取网页数据案例(随机网页) 6 @3 d& `& C l, O
`//导入模块`& Q$ e7 x4 n% o# f
`const request = require(``"superagent"``);` `//导入请求模块`4 E0 u" i. M8 y* w7 N t3 e, ?' R* L
`const cheerio = require(``"cheerio"``);` Q( O" v* P3 F# d& ^
`const {join} = require(``"path"``);`/ P8 }0 s, b6 x5 j
`const fs = require(``"fs"``);`3 q- b3 p* @! I
`let arr = [],` `//存放数据`" G% k' Z( U/ j1 {! R
`reg = /\n|\s+/g,` `//replace中使用`
; x. i: T0 S. Z# \# t3 B4 Y! t `url =` `"[https://www.shiguangkey.com/course/search?key=%E5%89%8D%E7%AB%AF/](https://www.shiguangkey.com/course/search?key=%E5%89%8D%E7%AB%AF/)"``;`5 I( u+ S- q8 Y( F. Q
`request`0 }# f) U% J7 x; N
`.get(url)`' v2 A1 A; G, B* a: Q
`.end((err, res) => {`3 o5 |# C6 o, q2 K
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`3 x8 b d/ h# a* ]9 ?, F
`$(``".course-item"``).each((i, v) => {`3 x% c$ t, K S' S
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`1 \" l$ N( o$ y( \% ?
`const obj = {`2 N9 C; y1 Q1 ?7 n
`imgSrc : $(v).find(``"img"``).prop(``"src"``),`
9 G3 j4 N& ]1 U; A0 m' W5 f# i# M U `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
- z' M- p9 |$ s3 y, M `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
1 {: a/ s. F9 V. n* s7 I `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
! c4 p2 G4 K, A) j k2 s `};`
7 i( b5 V! e& V3 K7 S+ o6 z1 c `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
- M9 ?: j: r4 T" Q6 A- r# s `arr.push(obj);` `//把对象放进数组里`
2 G& {) _0 E" S- V `});`) \3 T* _9 Z6 D9 M; `6 `7 T
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`: U1 p- j& V# \( W
`});`
& h/ n0 B* R o 以上就是本文的全部内容,希望对大家的学习有所帮助
6 U6 N9 Z' c1 A1 ~; F) u, P# ?0 P. y% _$ @
) U0 E. O9 w) g b% t2 R- B7 ?5 P' @+ ` i+ j
- b" D4 ?2 N. J' L, M) L4 d |