/ s4 W k8 F1 M/ B Koa -- 基于 Node.js 平台的下一代 web 开发框架
8 v2 \# I+ ?- r" S' E; M& o5 T o koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
8 \4 _. @' Q* P% J) Z' C5 r 英文官网:http://koajs.com 9 ?4 W3 r$ M0 L' X* Q& l5 q
中文官网:http://koajs.cn ( z- S& Q# l+ \2 |0 b, Z5 v
1.koa 3 h9 U' P# W& o" R F
安装koa包: npm i -S koa@latest ; I( |2 k& g4 n) \8 o# {1 X( f" Q
引入: const koa = require("koa"); 实例化对象: const app = new koa;
, _1 X9 z( {6 a, W6 Y 通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册
6 w% b2 p6 J {& `! e A- n- T: | use()函数中必须使用异步 async; use可是调用无数次;
0 N. B' @, i" L$ x4 l" i 其中有两个参数: 3 ?/ N0 G/ J+ d3 T" D0 r
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 % R+ | i1 z, }) V$ g
b)next: next(),将本次控制权交给下一个中间件。
9 |& b0 Z+ |, M$ e/ w x 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 % G% J j3 N& o
1. next参数的使用demo
7 E! j5 i z* H `const Koa = require(``"koa"``);`
& e# v' r$ @. Q: g `const koa =` `new` `Koa();`, F: H6 v' x7 H2 p
`//中间件1`
; q& h3 ~" I N' V `koa.use(async (ctx, next) => {`& H( b" _7 Q* s/ t2 }. l+ ^
`console.log(``"1 , 接收请求控制权"``);` U0 V! q' ]" o4 E4 E0 }9 \
`await next();` `//将控制权传给下一个中间件`: [9 a) V4 }8 }8 l4 W
`console.log(``"1 , 返回请求控制权"``);`
4 J5 p0 Z1 y+ I% l `});` `//将中间件注册到koa的实例上`
1 S( ?7 O% [! w! I- z& I: F1 G `//中间件2`/ L1 z6 |0 i: [5 M! V8 \4 A
`koa.use(async (ctx, next) => {`
& d: M. ?7 o- c8 R4 v- M `console.log(``"2 , 接收请求控制权"``);`
; z4 J7 F$ p% ?/ s, u! o' n2 E await next();`4 [7 |$ x1 T h4 M3 E7 E. \
`console.log(``"2 , 返回请求控制权"``);`$ }- n" A( t5 U) ^
`});`& X% u& n# \* a0 @9 g
`//中间件3`5 y: q1 W; c2 W: H* ~
`koa.use(async (ctx, next) => {`
) t7 w1 t# g/ L1 |* B! P8 X% d `console.log(``"3 , 接收请求控制权"``);`! ^5 i$ ]7 \$ c& I! J
`console.log(``"3 ,返回请求控制权"``);`: ^3 j. w+ P% i
`});`7 P D, N& w% e/ c8 K! h2 ^
`koa.listen(3000, ()=>{`
4 @3 e+ l( ^5 }6 h `console.log(``"开始监听3000端口"``);`
2 N) g$ o" `$ m' d% P9 P `});`
, c/ |& Y* J7 D7 u$ {2 O) ~& I 注:当中间件中没有next(),不会执行下面的中间件 2 T+ R/ R+ N4 a" y( h6 Z! L
访问localhost:3000的效果图;
/ P" s2 d1 R6 Z9 I" Z) n
3 o y m, a) r% r8 s 注:会有两次操作是因为图标icon也会请求一次 ! k- I% j' s: _. ]) F- R
2.ctx参数的使用demo
4 g" l9 p$ X- j5 r" e1 K `const Koa = require(``"koa"``);`
/ J% ~: ]1 W7 } b, f7 W$ Z `const koa =` `new` `Koa();`
) w2 P5 T- ~4 p& e) c' l, Q `koa.use(async (ctx, next)=>{`
4 X" R- u5 A( ^2 U3 v `ctx.body =` `"body可以返回数据,"``;`
: r% u A( g8 J5 M \ `ctx.body +=` `"可以多次调用,"``;`
, C3 F! g9 D7 l7 d3 g+ t! U. M `ctx.body +=` `"不需要end()"``;`3 R% P9 R9 v2 d1 ]. ^0 |
`});`
. j5 q7 Q/ n& e* ?+ N4 F `koa.listen(3000, ()=>{`+ [" R9 Y# B4 T* D
`console.log(``"监听开始"``);`
4 Y% O+ S; j6 s! ^# r# S3 V2 `- ] `});` . n+ D1 E! B" J
效果: ; P2 v' A$ m" g7 q/ K: d
, [) B3 g0 o# d$ Y
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
$ m9 o2 y& U) U/ N `const Koa = require(``"koa"``);`% v/ {9 [9 J5 J6 y7 n+ P4 P& D' d
`const koa =` `new` `Koa();`
r* p" n8 d `$ r' C1 z3 P `koa.use(async (ctx, next)=>{`$ t6 J4 U0 P9 Y9 g6 ^0 X% g
`ctx.body = ctx.url;`
7 s# i! n) t) v6 z( J6 b `ctx.body = ctx.path;`
/ M+ p( |6 W8 Q3 Z) j \ `ctx.body = ctx.query;`
& ?: D% s* c1 c) X8 z$ K4 K `ctx.body = ctx.querystring;`" Z1 C1 w$ V2 ~, p
`});`
; K; v2 K, \8 r" f. [5 [ m `koa.listen(3000, ()=>{`/ a: a2 Z5 }9 }. J" Y
`console.log(``"监听开始"``);`
4 X0 E( h, [8 q j/ n" q' o `});` ) M, ~3 W* W/ i) R# q/ y( T! N
访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
1 h" W6 X& ^; x- E: z 1. url: 整个路径 ; X: }& q# x8 C& K; w& j
|4 g% a: J4 j4 q" i. R5 T# c. N 2. path: 非查询部分 ! y" p4 C+ W9 d; S- ?- {; c
+ ^, y! q3 Y8 M( q6 \
3. query: 将查询部分转为JSON对象
X* V: L0 z8 H4 v: [7 f6 ~ 5 \# t2 i4 n' K* G' [+ m! @ z+ f
4. querystring: 将查询部分转为字符串 - M1 r( }/ O, M/ t8 n! O/ `
5 b( A' c5 A2 _/ |0 ~
5. ctx.state ,ctx.type 表示状态吗和类型 1 N# w0 R) E$ R. }) E
2.简单爬虫练习
3 U5 g, S0 i; W, c* K+ ]( s 安装request,cheerio模块
' }% P/ @& T) x `npm i -S request: 请求模块`
( q$ ^. j, L! S C2 z2 D) Y `npm i -S cheerio: 抓取页面模块(JQ核心)` 4 q: i2 c/ ?0 M8 ^) Q$ T/ P
抓取网页数据案例(随机网页) / z$ O; P3 f$ v( V
`//导入模块`
[ O/ x+ n( z$ V, | `const request = require(``"superagent"``);` `//导入请求模块`2 [5 }3 D) e' k6 Y0 x! F$ T0 Z( P
`const cheerio = require(``"cheerio"``);`- e$ x. @$ i9 E* Q# ^
`const {join} = require(``"path"``);`; I9 L5 }% f8 \$ E8 h1 s/ u3 S# k
`const fs = require(``"fs"``);`
l$ a5 Y9 L* G9 w) k3 z9 G- U8 X. J `let arr = [],` `//存放数据`6 }/ u% L3 b5 m0 B/ E
`reg = /\n|\s+/g,` `//replace中使用`. `8 P# z- a) S+ S# P
`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/)"``;`8 C V* E* a; `: e9 k# M% X1 ^
`request`; e# {. \) v9 N! y
`.get(url)`
8 ]4 Q# ^1 o% ?2 R7 P' a `.end((err, res) => {`
' ]2 S A7 w; W3 I Y7 V `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`6 e4 f: v* H6 r. F$ q, L8 h2 U
`$(``".course-item"``).each((i, v) => {`+ Q2 I$ w: i: D' f" c* E F
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
& C, b2 g% J5 Q `const obj = {`
8 |% }6 h3 \6 g) W# g! y. v# H0 w `imgSrc : $(v).find(``"img"``).prop(``"src"``),`
7 b0 c% U3 e* Q' _& a6 j `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`; { p# I# S2 i, }' [( j
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`! B4 X& ?' X F
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`; f, m: l8 _; z) `3 E J
`};`+ Y: y( d* K3 o
`console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`3 L- J: H2 V0 i6 M
`arr.push(obj);` `//把对象放进数组里`1 a; t6 [. p/ P: X( y5 d% H6 S
`});`( h; w7 z' @5 F+ S
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`) O' l* e4 V% m
`});` ) u7 o2 { T, a1 K6 U
以上就是本文的全部内容,希望对大家的学习有所帮助
. h. P) c/ D6 m; \
0 m. ?0 @ I$ [( K
9 `8 @+ H5 z1 z T. N) \: \ E \' L# D
; N8 d4 k. Z" {
|