) V! y5 R% ^9 W/ J% r Koa -- 基于 Node.js 平台的下一代 web 开发框架
, R3 S- B+ s( K5 X# E9 W1 g# D koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
0 Y" ~0 S5 n0 P' Y( d 英文官网:http://koajs.com
$ K( F" d; u0 e, T# a* U 中文官网:http://koajs.cn + y/ \. a5 W" f8 C1 u! m
1.koa
& `* S+ r( W+ }) ?3 p 安装koa包: npm i -S koa@latest
6 ]% }8 {: [0 ~ 引入: const koa = require("koa"); 实例化对象: const app = new koa;
& H; [' ?6 O2 t3 H4 Y2 s# B" f g 通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册
* T v9 O, i8 b4 g) C% f$ h use()函数中必须使用异步 async; use可是调用无数次;
* w5 A. M5 M- ~! Z 其中有两个参数:
5 G3 w& h+ @" {8 s( Y& w$ s/ Q) \% x a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
) g7 z) ]7 J, H% H0 z! M% U$ ~ b)next: next(),将本次控制权交给下一个中间件。
. ^! H( ^2 @0 v O% ~* `. s 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 / _* H5 W9 p! i1 D+ @2 ?; x
1. next参数的使用demo
- q1 z4 r" L! G+ k `const Koa = require(``"koa"``);`
/ }) e# z, ^2 Q9 |; p5 M/ ~' t `const koa =` `new` `Koa();`
+ _7 D9 K. x' r+ Z `//中间件1`
# e1 Y+ }1 Y& z. @, U0 Z `koa.use(async (ctx, next) => {`* D3 K+ M6 V# }$ b
`console.log(``"1 , 接收请求控制权"``);`1 V# ~ E ^+ N# o$ N
`await next();` `//将控制权传给下一个中间件`+ ~3 m( e, Y0 C% T5 C$ H. S4 _
`console.log(``"1 , 返回请求控制权"``);`
. \5 m% G: l: b( M2 y! A2 f `});` `//将中间件注册到koa的实例上`; s' p1 g/ ^8 z
`//中间件2`% `# l; ^; W" ~7 X8 T4 j
`koa.use(async (ctx, next) => {`
, s! P. y) i0 h& [+ U5 c- K `console.log(``"2 , 接收请求控制权"``);`
- s. M% \" e5 U/ x# W& A# O await next();`/ g# w* J. e( v+ F' q$ q9 q
`console.log(``"2 , 返回请求控制权"``);`. H: V& F I- t/ R- ?3 G
`});`% c4 B' W9 ]" F/ i6 Z& C
`//中间件3`
& \! D7 T2 K. E( l l `koa.use(async (ctx, next) => {`
, i% }& |: d' B( W7 _3 _7 [ `console.log(``"3 , 接收请求控制权"``);`% r' }6 ^% w* r- [& a
`console.log(``"3 ,返回请求控制权"``);`
; o- O. P) V* d! B! N0 G9 z `});`
9 w8 a# T9 N3 z1 {- ] `koa.listen(3000, ()=>{`' ^7 u2 [& X0 g/ c
`console.log(``"开始监听3000端口"``);` I' f, s4 k* A1 f
`});`
) D2 s# ?, M! `; y" | 注:当中间件中没有next(),不会执行下面的中间件 $ [9 X: }2 i* o+ a7 F5 J" H1 Z
访问localhost:3000的效果图;
# X# ]% H/ u% S/ Z0 Q 0 U1 R7 O+ I. h* i8 K% l3 M6 M
注:会有两次操作是因为图标icon也会请求一次
& e% D! k5 x2 j! _# `6 S. i 2.ctx参数的使用demo
5 c! c9 U1 P, N) s( ~2 M `const Koa = require(``"koa"``);`
1 T. S6 `9 r$ k0 Z; e3 b `const koa =` `new` `Koa();`& W9 a/ Y6 ~; F, U9 }
`koa.use(async (ctx, next)=>{`
( i; d; c1 c' E) Y `ctx.body =` `"body可以返回数据,"``;`
; C' m- a( F& }& L/ W `ctx.body +=` `"可以多次调用,"``;`$ C ~9 E, m) F2 k; U/ w1 `
`ctx.body +=` `"不需要end()"``;`
0 ?0 H" n" I! T9 |/ f F, ^ `});`' I& t) h2 `; q' B
`koa.listen(3000, ()=>{`
& [( G7 R( a: f7 H `console.log(``"监听开始"``);`+ [( ?+ q0 n; ?9 @. y: W: ]. }
`});` 3 P7 Q0 h9 ?2 }& J- b& J d
效果: ( p+ f% }6 J8 L
* t6 E5 T2 y t6 i( ^+ [3 H5 m ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type 7 z9 G4 y2 N5 q9 H# J* C3 W
`const Koa = require(``"koa"``);`& w- Q( {) C3 z7 o0 }! n+ Z" G
`const koa =` `new` `Koa();`: [+ f6 \( s! ~( }( m) r5 m
`koa.use(async (ctx, next)=>{`" n- g$ g9 b1 Z2 o
`ctx.body = ctx.url;`
* F. O* P6 Q" x5 P `ctx.body = ctx.path;`
$ n, Y. o9 V- e `ctx.body = ctx.query;`1 f# S E9 B2 X7 `
`ctx.body = ctx.querystring;`
@+ Y9 E% V# \8 k6 w `});`3 @# G5 H1 e; N" l1 z
`koa.listen(3000, ()=>{`( A. w' }5 U9 b6 G& l
`console.log(``"监听开始"``);`
+ T2 W: ]7 _' Z" j, i0 W" t( | `});`
X0 z& O' j0 N 访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
5 r$ h0 V; p. C$ x# O' A! \ 1. url: 整个路径 0 S9 H& l! p4 G1 }% j* j
' z R: @5 z9 ^5 ]: {! i
2. path: 非查询部分
7 W9 B1 i; I% I5 K% ? @% A7 v u" t, Z3 N; m
3. query: 将查询部分转为JSON对象 8 h1 g8 ?( a. a+ [# I' E* }% u
/ g& i+ f- ]8 J# S* t5 p( I: k 4. querystring: 将查询部分转为字符串
8 U% k: j0 l" Z- L! x
9 F4 I* c, ~/ C3 X) R 5. ctx.state ,ctx.type 表示状态吗和类型 - U# {8 T% x2 F" {# c- c
2.简单爬虫练习 6 G- C' O1 S9 x
安装request,cheerio模块
4 ]* u! F& B. N) I) J `npm i -S request: 请求模块`
5 G8 j( L/ w7 p; t0 n W) Y% ] `npm i -S cheerio: 抓取页面模块(JQ核心)`
6 [+ k! q. N( M0 {* j1 Z 抓取网页数据案例(随机网页)
3 |+ g$ `/ e1 f+ M& e$ E2 E `//导入模块`
! w R9 O& A, J5 J `const request = require(``"superagent"``);` `//导入请求模块`
) J) o5 z+ M, b3 Z `const cheerio = require(``"cheerio"``);`
) I- A; e, A; \( o/ B3 @3 ^" H `const {join} = require(``"path"``);`4 w' b! Z: U# A
`const fs = require(``"fs"``);`1 G0 S( }; D. _7 `+ [2 j9 [
`let arr = [],` `//存放数据`4 L8 Q6 c8 z+ }$ T) u$ m' c P
`reg = /\n|\s+/g,` `//replace中使用`7 Z* K& a, p& p- X* Q
`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/)"``;`
. }7 ~! a) G( `8 [* P. ^ `request`1 U, m1 t8 Y4 T& M& ?# U
`.get(url)`$ C4 }3 [! q7 K/ t ^
`.end((err, res) => {`5 ~6 u; n6 C. ]" |) ~
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`% ]" U0 E4 H7 l, S9 e! w/ e
`$(``".course-item"``).each((i, v) => {`
' r$ `7 j& H8 i' w* C. L: }$ a4 y' D `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
% E. A9 C% q! l8 W& \$ s. ]8 T `const obj = {`5 b! n, d9 n! n# I8 G
`imgSrc : $(v).find(``"img"``).prop(``"src"``),`
0 {" h) l" s+ `1 t% H. B8 W `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`- q5 R8 r* p+ T( H
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
1 j/ k) f, P/ Y5 c0 K: [, r `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`7 M$ {: R) v6 }! t4 O
`};`
0 q: b- O9 u8 d2 D& s; Q `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
}, e; _4 B& x6 o0 f$ F `arr.push(obj);` `//把对象放进数组里`
% a7 Q) E$ ]4 Y `});`1 p* q' v" S" }( G5 k+ t
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`! J7 z, N6 X8 K* A; ]
`});` ' s b3 `8 e6 }' m* h" w: g2 H: k
以上就是本文的全部内容,希望对大家的学习有所帮助
& q, g# `) t$ u/ J; j, J+ Q1 W0 U. G/ B- _, p
, Y* h+ {# | _0 A# @( \( m$ g* h
' F! _+ f2 L+ s
|