+ b9 y {( T$ |8 J( c7 G
Koa -- 基于 Node.js 平台的下一代 web 开发框架 6 J% b$ [& ^3 }+ @) u- M
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 7 V& V4 \' a- c0 _
英文官网:http://koajs.com 8 Q0 g9 _1 C# M' g
中文官网:http://koajs.cn 3 v7 W& ?/ c& O
1.koa
8 L* `+ K0 L2 C. r; ^% o6 N$ b 安装koa包: npm i -S koa@latest
4 L7 \) M; u+ ?4 a. n% c 引入: const koa = require("koa"); 实例化对象: const app = new koa;- w% W( E% X% [$ l( j
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 , Y" ^$ w# Z( P% R' P9 v
use()函数中必须使用异步 async; use可是调用无数次; ) K$ E9 l ?1 F& w+ J/ g! n
其中有两个参数:
' j0 Y/ s: O7 @1 ?( v a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
& ]; ~& g, ~5 @+ O2 e2 v b)next: next(),将本次控制权交给下一个中间件。 % E' [6 r: J2 l' y/ J4 F8 {
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 4 T8 R+ |3 p2 L$ \% K% T' Q
1. next参数的使用demo , O; R4 _; F; P/ a0 Z
`const Koa = require(``"koa"``);`
0 m) w# }6 @8 A7 o `const koa =` `new` `Koa();`4 T8 l4 N2 z7 F5 ?9 ]
`//中间件1`
) w; D! A, k% ]& x' R' t8 A `koa.use(async (ctx, next) => {`( B f% h" c- n
`console.log(``"1 , 接收请求控制权"``);`
h; |4 ?2 S# t( e0 K9 j `await next();` `//将控制权传给下一个中间件`
. c& a7 @# V3 o2 W `console.log(``"1 , 返回请求控制权"``);`- U! w! y1 n2 U6 H- M
`});` `//将中间件注册到koa的实例上`! { I p; p3 `. S7 m2 ~
`//中间件2`" Y" Y* i2 o" q) {2 p
`koa.use(async (ctx, next) => {`5 s# e j7 I) U6 \7 V3 m/ t6 @
`console.log(``"2 , 接收请求控制权"``);`
8 H. M) [. M7 u$ E await next();`. v X3 @' _* s8 G+ P1 s
`console.log(``"2 , 返回请求控制权"``);`
. b2 } X- V3 | e `});`$ p& _; e$ S6 R- S2 Q
`//中间件3`9 g0 F2 z/ H" W u
`koa.use(async (ctx, next) => {`5 G7 I: A$ z D
`console.log(``"3 , 接收请求控制权"``);`
8 r( ^$ Y( D) G! C `console.log(``"3 ,返回请求控制权"``);`
8 B8 i+ K4 Y0 s5 H ~ `});`
: ]4 m7 j- E) ^ `koa.listen(3000, ()=>{`8 S% @4 i& w- N# D' ^$ R
`console.log(``"开始监听3000端口"``);`
1 C" B4 ?1 @; g8 a7 W `});` 9 }4 u/ N- ~9 `- o! B
注:当中间件中没有next(),不会执行下面的中间件 ( z7 a2 ]5 b3 N6 W2 X C
访问localhost:3000的效果图; ' t5 ?* `: A( l* s* B& B9 O
X1 [. q+ c4 v% j K6 r 注:会有两次操作是因为图标icon也会请求一次
. C p) y& _: n6 R1 Q% R, F$ D 2.ctx参数的使用demo 3 F* E1 G; U0 P" n+ E1 i
`const Koa = require(``"koa"``);`, O- I) d5 I0 `& X
`const koa =` `new` `Koa();` w3 g8 A( i% N/ c0 I7 l, ?
`koa.use(async (ctx, next)=>{`
" }1 f; \/ |" s( f" B' I `ctx.body =` `"body可以返回数据,"``;`/ x4 ?2 h U1 ]
`ctx.body +=` `"可以多次调用,"``;`# h. [' O: e/ f2 l8 s$ q
`ctx.body +=` `"不需要end()"``;`
* z0 B7 y3 K" b$ X% @% V `});`* i5 E* e7 W6 f9 ]6 P9 G
`koa.listen(3000, ()=>{`
" g% X1 X s) V0 Z `console.log(``"监听开始"``);`
/ `, P+ R5 V& ?, L: V `});` ) h: i, L% N1 m$ w0 ?
效果:
: T% N! X' ~5 ?
, K/ P$ x3 Q( p# W, u: ? ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type 7 M& a4 K- w" {) n5 c5 w
`const Koa = require(``"koa"``);`
& ?9 c* x+ S5 ^- v; Q `const koa =` `new` `Koa();`
% c/ m# v/ Y9 n! Q; K q `koa.use(async (ctx, next)=>{`
4 Y# t1 Z% Y/ W4 Z \# b8 h/ Q `ctx.body = ctx.url;`
! W8 I* R/ x8 q/ o9 }! k G `ctx.body = ctx.path;` L0 w1 o# N, m( ?* K' p4 u
`ctx.body = ctx.query;`
; H6 D; u; ^+ g4 { `ctx.body = ctx.querystring;`
( q1 ^7 H' R( G0 T S `});`
7 ]0 I) W' b- N7 Y1 M$ w `koa.listen(3000, ()=>{`/ L0 {5 G+ i# ?, X
`console.log(``"监听开始"``);`2 B% L' f, C |6 u- R
`});` 0 f" g3 W( M7 Z( J
访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
$ o; R( K' ~ D1 H/ J" p$ v 1. url: 整个路径 1 t6 A! P3 s6 J: {
7 e3 ~& N5 S" b9 o- p 2. path: 非查询部分
8 q; \9 f+ H% e. z! p ^: E" A
+ T5 Y* s0 H1 C. ~; r \( C 3. query: 将查询部分转为JSON对象 5 @7 H6 |: n: _$ ]- P) E) C8 \. l
. L6 x+ g! j: p' M: T5 x0 k 4. querystring: 将查询部分转为字符串
# G- j* l" j, _4 h8 g * p8 G2 [2 W& C& _; r; y
5. ctx.state ,ctx.type 表示状态吗和类型
' ~1 }2 t! z: O% H 2.简单爬虫练习
/ P6 F# j7 {9 S" H. a 安装request,cheerio模块
* Y N! ~4 j- f: r/ Q8 v2 Z `npm i -S request: 请求模块`/ g+ o, L9 i9 f) _, J
`npm i -S cheerio: 抓取页面模块(JQ核心)` * d* S+ p( Q% @0 D3 H# A* u9 i% Y; ~
抓取网页数据案例(随机网页) 3 ]" ?% J" h9 _. s0 D
`//导入模块`( _" H" \. f) t; u T+ v, V
`const request = require(``"superagent"``);` `//导入请求模块`: F: U2 k b+ T! t- y
`const cheerio = require(``"cheerio"``);`
; k& b% t! q! G' u6 v/ d- l% \ `const {join} = require(``"path"``);`
6 ^+ g. { f5 J+ P% ]. S: _. j `const fs = require(``"fs"``);`: C/ V3 v$ Q1 k; H
`let arr = [],` `//存放数据`
3 c2 D, c+ C; M D: s `reg = /\n|\s+/g,` `//replace中使用`1 K" K- C* m, 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/)"``;`; e; m# x3 R$ Y! Q+ o9 L2 C- W
`request`
0 }# m9 h% B4 O/ l `.get(url)`! ~+ }( o$ k9 ?! t2 I
`.end((err, res) => {`
3 G& E' I2 G. ]: f' Y% P `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
5 r \& {: o4 ~( u `$(``".course-item"``).each((i, v) => {`
; k/ H5 q" T- B1 j& ~% a `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
# ~/ g, J/ {- B% |5 W! B `const obj = {`" {% n& \. ]. i5 P. b3 s( R
`imgSrc : $(v).find(``"img"``).prop(``"src"``),`% M3 I6 i/ o# `% ~/ w. E
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`' M- N3 y6 h/ A/ [
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
* h1 i$ v. D/ Z# l, T# w `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`% B* r. R8 D' Y7 B& h3 S1 b: I
`};`8 H& R7 b7 Z: e- O) a9 l" n
`console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`2 I: V) R+ p8 U9 ]5 f3 a3 [; U+ ^
`arr.push(obj);` `//把对象放进数组里`
0 H0 D4 T! M( B) Y8 ^+ f, F/ m `});`
" b# L! n' T- U0 H `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`; r1 B. F) F+ H. L
`});`
( K4 c1 O8 D9 r- \ 以上就是本文的全部内容,希望对大家的学习有所帮助 a, P5 b/ Z' v- U% b4 S. H, y. g
. I' G+ H3 j) }
$ T1 ?, r, @3 X) K. l, ^3 T, `* _: a$ ^% |
# e X: b; L$ ^9 R) @: i
|