|
w x* R' v; U" x* q8 g8 _ Koa -- 基于 Node.js 平台的下一代 web 开发框架 . T* }6 C% ]3 U/ v' t7 {6 C, R8 h
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
6 R& p! J! i: |7 R7 @( U 英文官网:http://koajs.com * h- |+ O. G. y; i4 r- b5 m
中文官网:http://koajs.cn ) J s7 O8 o6 D
1.koa
4 Q8 C- c7 t3 s3 ^9 v& y6 a 安装koa包: npm i -S koa@latest
, Z/ r& R2 ~. m7 G! z: G* e& J5 m 引入: const koa = require("koa"); 实例化对象: const app = new koa;) Q, U9 V" s: [' `6 j) h l# w
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册
* Q: [2 k/ d2 j4 e+ p- l# V use()函数中必须使用异步 async; use可是调用无数次;
0 B" w3 \: v4 p& z) n: Z& h) o 其中有两个参数: 7 ~$ `: j$ L$ @$ J
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 7 Q! N) |- e! \0 X% j; W7 d
b)next: next(),将本次控制权交给下一个中间件。 & x# L' X$ v; b
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 7 s. w; }; Y; ]# [9 ?5 \1 d
1. next参数的使用demo
8 p6 `- q6 N3 M& D9 K% A! R `const Koa = require(``"koa"``);`6 N- ~4 [8 a1 D: p; h0 G- r
`const koa =` `new` `Koa();`7 i3 x1 @) d; e3 v' H0 o5 o5 S7 i+ Q4 p
`//中间件1`7 D. h! \1 Y1 r6 P! \
`koa.use(async (ctx, next) => {`. Z. E# f# z( q+ W a* Q9 l
`console.log(``"1 , 接收请求控制权"``);`
$ a2 ?) a3 y; I/ K! c4 _ `await next();` `//将控制权传给下一个中间件` h9 {$ T- K' J
`console.log(``"1 , 返回请求控制权"``);`
' f$ F: D% k: I! @: f/ ]' ] `});` `//将中间件注册到koa的实例上`
/ ^/ g' r: G. i, C7 c4 K `//中间件2`
% k/ Q! L2 }$ C* P- @ `koa.use(async (ctx, next) => {`
5 b7 X. [/ h: w/ A1 d `console.log(``"2 , 接收请求控制权"``);`8 i8 @/ \7 i: q6 U, o5 L/ q( P. b
await next();`
; h" @7 V. y9 u1 {* L6 h2 [ `console.log(``"2 , 返回请求控制权"``);`" J3 h3 S1 X( k% }; t% ?
`});`
, g7 [/ e4 z! Z) L: _/ P1 W4 F `//中间件3`* R; V2 @& W+ W8 d
`koa.use(async (ctx, next) => {`( U% B3 Z; {5 s7 M9 j) W' K0 A
`console.log(``"3 , 接收请求控制权"``);`
& S+ @* M1 Y+ u2 T6 b4 N* h `console.log(``"3 ,返回请求控制权"``);`6 n# Q& l0 A8 f, K
`});`
) h, c0 j+ @; Q+ v `koa.listen(3000, ()=>{`7 h+ X/ t O# t6 L3 n
`console.log(``"开始监听3000端口"``);`
$ D" Q) s/ @/ G* ^( F9 A" [- C `});` 5 ~+ N3 N+ r0 i9 A: H0 Q* [6 I9 B
注:当中间件中没有next(),不会执行下面的中间件 ' O6 t' r: K) Y
访问localhost:3000的效果图; * Y7 B8 C5 D% t0 a3 s
+ K. E& G9 _6 F, J; J2 q, k 注:会有两次操作是因为图标icon也会请求一次
2 V S' `9 e# A* u/ N7 n 2.ctx参数的使用demo 6 x: g4 l5 _( l; B" N& X; F
`const Koa = require(``"koa"``);`3 a1 v5 T `6 f6 `5 M
`const koa =` `new` `Koa();`
5 s) i; x" }( n" }; V2 E" w: |5 J9 V `koa.use(async (ctx, next)=>{`
) T# f( b" v% v `ctx.body =` `"body可以返回数据,"``;`) R& O* @% f! ~& J* k
`ctx.body +=` `"可以多次调用,"``;`& P1 `+ H; r4 Y" L3 O, i5 Q' U
`ctx.body +=` `"不需要end()"``;`
; k0 D3 H+ ^2 o: {7 B* d! O `});`
2 T$ q; [) @5 c) K+ k `koa.listen(3000, ()=>{`
9 K9 a t; {2 ^* M2 Z `console.log(``"监听开始"``);`
& r% N e6 X) V3 Y `});`
7 \) k4 f8 X8 }/ S2 b 效果: ' v3 M, @- c6 f& ?6 {; ` W
5 t% `$ ~7 G7 y, ~
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type ( V q% }# u S. o" X) ~' f
`const Koa = require(``"koa"``);`& g1 G& e% n0 N4 J# {: W M# o
`const koa =` `new` `Koa();`
: D# T5 a( z( F* g8 m4 n `koa.use(async (ctx, next)=>{`
, {2 C' y( O3 V: `8 u5 s `ctx.body = ctx.url;`1 p; k* B9 p$ R& y
`ctx.body = ctx.path;`/ t' Z: F( v1 n4 |0 L. R0 E
`ctx.body = ctx.query;`
6 s# u+ `# H c$ A! }3 ]/ l, p `ctx.body = ctx.querystring;`& D5 z; C; p) C, }* U" }+ \# j3 p5 T
`});`
Q' B5 h2 v) h: F `koa.listen(3000, ()=>{`
3 \: o7 b, t" `; J/ E1 `# j: ] `console.log(``"监听开始"``);`
% E. C! s' n) k* j `});`
9 {& O/ z; K+ l0 w7 p+ ~' ] 访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
' Y; J! ]" g/ ^* G: m! E 1. url: 整个路径
' F, }! V' R7 i- [( w2 L1 y9 L' q
, x, T* _0 J" P/ p5 H: S 2. path: 非查询部分 2 O+ d/ l) B2 J0 w3 S1 @
5 A) Y% E5 i& W) |0 B+ h9 N3 ~ 3. query: 将查询部分转为JSON对象 2 o9 l* Z& [' G& P, c1 Q' J
k% q8 M# I: \5 e 4. querystring: 将查询部分转为字符串
& W8 S) Z* W1 {
* e! O: G* o6 {0 [ 5. ctx.state ,ctx.type 表示状态吗和类型 8 H8 p$ c* k3 B B7 i) K2 d
2.简单爬虫练习
: k0 L! e" w0 M2 q4 U! w 安装request,cheerio模块
% b/ @, w; W- W4 H) m5 D- ?( s! w& T `npm i -S request: 请求模块`. L$ H# f" M$ r* n
`npm i -S cheerio: 抓取页面模块(JQ核心)`
, ~& s; r( N4 H: |! D& u 抓取网页数据案例(随机网页) % N6 v6 [/ s( c4 W- Q
`//导入模块`
- O# d* o* A4 _: C6 h* n `const request = require(``"superagent"``);` `//导入请求模块`' @/ A" D+ A5 q5 C, F0 Q
`const cheerio = require(``"cheerio"``);`
, ~4 f6 N$ j5 d% ^; P `const {join} = require(``"path"``);`1 b T% M7 q( l" W V% B# j
`const fs = require(``"fs"``);`6 H" s2 d- f" t3 B
`let arr = [],` `//存放数据`
( v) G/ J. X6 Y6 h2 H3 { `reg = /\n|\s+/g,` `//replace中使用`$ `6 L; C- f' i
`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/)"``;`
W# ?' C% \ X& Z( ^ `request`0 }8 _6 _3 ^4 @* n5 M9 p2 w5 Y- o
`.get(url)`
3 c- v6 @; P8 C4 z% Z* w# h8 Q5 N9 F `.end((err, res) => {`& ^* v# B. [: t/ i% H
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`2 Q4 A3 X' {. U; \
`$(``".course-item"``).each((i, v) => {`7 J6 j* y/ _& K! U5 v
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`3 w0 ^- k4 v+ J/ ~4 b
`const obj = {`- |* ]) I' _5 P
`imgSrc : $(v).find(``"img"``).prop(``"src"``),` }; {7 C9 {( D& Z, `2 H
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
. I }) J* w- M8 w! y `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
* a8 V0 ~0 M& G/ u. t `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
& @5 y- q# x# R# }+ f `};`
( p, x" `* U2 `2 U( T6 {7 ~ `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
, H3 B( F9 |4 e; z2 w4 p `arr.push(obj);` `//把对象放进数组里`
9 i6 c' V1 h0 L0 e, d `});`: a; d/ ^' D6 f& V/ t
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`
' G+ I9 c X! P9 W1 o! X( O `});` 0 k% ?! ^8 ]" W- N! |1 Z
以上就是本文的全部内容,希望对大家的学习有所帮助
/ q% R$ E- O# [: v6 C U- u% J" T. y! K& Y5 ~
1 [0 i F5 A; ^7 {- j3 Y2 C
: a8 n$ r% A* D+ e) O b( S1 m0 h& M. q1 p
|