! `& {* ]& J% N, z/ x5 F9 L
Koa -- 基于 Node.js 平台的下一代 web 开发框架 8 O# L! u1 W0 z# {
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
3 p2 w; n$ n8 Y* D0 F. }5 p 英文官网:http://koajs.com
2 D* c3 Q' C9 K& o 中文官网:http://koajs.cn 9 P3 [5 _; l/ T+ H* \
1.koa
9 d( `" L+ {7 e& N8 Q 安装koa包: npm i -S koa@latest h4 I. G$ X2 \" U* ^0 e2 l) o
引入: const koa = require("koa"); 实例化对象: const app = new koa;8 r6 y& z4 J# l' R( ]4 f8 j! l
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册
2 t J- Z/ Q$ k ` use()函数中必须使用异步 async; use可是调用无数次;
) P# b u: c; A1 k0 S 其中有两个参数: * r8 E$ \3 y' R+ o
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 . M' ?* t: A$ p4 ]% c% j
b)next: next(),将本次控制权交给下一个中间件。
0 n# C+ {4 o# X7 n- V. ?1 f 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 6 \! p6 G& O7 d$ O m/ v4 ^2 ~1 {
1. next参数的使用demo
! [+ z* s, X. i" @7 a3 P, u `const Koa = require(``"koa"``);`
' t# C# o' {6 U `const koa =` `new` `Koa();`3 P6 I1 A; ^4 b" Y
`//中间件1`4 v" o( [- R1 R/ W1 i3 g
`koa.use(async (ctx, next) => {`2 a W! G& h$ ?* T7 Z
`console.log(``"1 , 接收请求控制权"``);`
j4 J# ~$ a/ T7 S# ~- ^8 }+ R `await next();` `//将控制权传给下一个中间件`
" d% W* m! }1 ^* B8 \1 b# X8 N+ k, S `console.log(``"1 , 返回请求控制权"``);`
/ D& q- e$ p2 A- [ `});` `//将中间件注册到koa的实例上`
* `1 i: L7 M f& @5 @: O" H `//中间件2`
) s9 j& _$ i, T `koa.use(async (ctx, next) => {`! b0 i' u3 ]4 w6 `" e
`console.log(``"2 , 接收请求控制权"``);`
V. E8 D3 Q5 M ]1 X7 o2 \* J6 d0 O4 M await next();`9 v$ c$ X0 k7 S( E. X4 }! Y2 H L
`console.log(``"2 , 返回请求控制权"``);`, G- N; O6 U# J( p9 F
`});`* k# I3 C9 c e
`//中间件3`" a) l$ g% D. y6 ]
`koa.use(async (ctx, next) => {`
' S2 ^, o8 l/ U `console.log(``"3 , 接收请求控制权"``);`7 g# Z, B7 K" r# W
`console.log(``"3 ,返回请求控制权"``);`0 b: u& @% \* P4 a0 e) g
`});`* S4 a" W) U! t
`koa.listen(3000, ()=>{`7 F2 d* n+ f, T3 I# }2 K- h
`console.log(``"开始监听3000端口"``);`, Z! R) j9 {, w; d
`});`
) B- h- G& m0 `, I! j 注:当中间件中没有next(),不会执行下面的中间件
8 [* n4 L& v1 p2 }7 `9 j 访问localhost:3000的效果图;
* i& [3 d7 R% ~
7 l, S* x& s) Y; E- q4 e: y/ D 注:会有两次操作是因为图标icon也会请求一次
$ Z5 i6 k5 h! K& H6 y 2.ctx参数的使用demo # n$ j* `+ n9 X$ l9 Y q
`const Koa = require(``"koa"``);`1 a. i4 T) r3 U( v7 |' `0 r
`const koa =` `new` `Koa();` |6 J; }& n/ h% F7 r
`koa.use(async (ctx, next)=>{`
: u8 G6 y2 `) c6 o/ ?3 u# u `ctx.body =` `"body可以返回数据,"``;`
* B9 A& y7 s. m. S `ctx.body +=` `"可以多次调用,"``;`
2 i) z7 ~* i# t3 [ `ctx.body +=` `"不需要end()"``;`3 z9 \, {3 s' o: I
`});`
' H' t; x9 [# c8 Q `koa.listen(3000, ()=>{`
) x- O: R' b |! p `console.log(``"监听开始"``);`) o, G/ O9 ?/ t+ h0 p
`});`
1 W, t# D+ y; v+ B$ ] 效果:
2 [2 }8 Q, `6 ~3 L' P" Y
W: [+ z3 x- [7 q ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
4 o# Q# v& r7 t `const Koa = require(``"koa"``);`3 [3 O# P8 E" g. G4 Z/ F
`const koa =` `new` `Koa();`
& X! i) `% `- A" F, J0 @3 F. N `koa.use(async (ctx, next)=>{`) \, z0 q" W, V$ ~7 R: R
`ctx.body = ctx.url;`
5 A/ |. \1 p2 o. ~ `ctx.body = ctx.path;`/ n: o1 E u0 e/ R
`ctx.body = ctx.query;`- D5 H4 F% Z. J& h& T7 |
`ctx.body = ctx.querystring;`
& Z" ^$ x& F% P7 o3 h8 u7 h `});`% ~0 T; |% `% ]0 Z3 Z9 K, n8 W
`koa.listen(3000, ()=>{`
% ?% o) u4 E3 i: F" ? `console.log(``"监听开始"``);`
1 N0 n% U6 @ O: d. n `});`
* s0 S5 L6 t3 o; C& H 访问http://localhost:3000/path?name=sjl&age=18为例,效果图: . W6 g2 L/ s' G9 ^$ P' u
1. url: 整个路径 & f: `2 m$ \ u1 Z7 Q5 H
; Q4 @8 R5 x2 ^( r U2 r" }
2. path: 非查询部分
1 {. j& v/ p0 h' O H; i. B/ Q
2 \# J& Y" q9 y3 x) m0 {# Y1 l# { 3. query: 将查询部分转为JSON对象 0 |% e# b3 h; _- Y% A1 E* D% N0 v
' u. e, C& r- M0 Q0 q$ S9 ~
4. querystring: 将查询部分转为字符串 2 I, d# Z0 w; L9 ^& V5 Q: w
6 J: u8 i; _6 a; j" V# |( O0 X 5. ctx.state ,ctx.type 表示状态吗和类型 + k# x$ D2 f" G5 x
2.简单爬虫练习 , A# x+ y- H& A( c/ G. V% w6 c: S
安装request,cheerio模块 6 r: J. X- m9 q+ s% e( z; H0 w
`npm i -S request: 请求模块`0 M$ J+ S; f, M) z3 m
`npm i -S cheerio: 抓取页面模块(JQ核心)`
; }3 g. Y1 Z3 p2 } 抓取网页数据案例(随机网页)
& a0 G/ c% E$ J1 `# ?" a `//导入模块`
3 m% g1 v/ |& U6 R/ t& w9 @8 Z `const request = require(``"superagent"``);` `//导入请求模块`& Y; }- Q- |0 v
`const cheerio = require(``"cheerio"``);`' W: \$ a$ d2 j' H
`const {join} = require(``"path"``);`
: f7 x3 ~1 W8 r& _! O# i `const fs = require(``"fs"``);`
& Q0 c8 h, m" n2 x/ x9 M `let arr = [],` `//存放数据`
% u7 L$ y; ?( O N `reg = /\n|\s+/g,` `//replace中使用`
9 ~* u9 H8 H& \$ L a( F, k/ 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/)"``;`
" @ X0 ` x5 f9 r" l3 k `request`- T% c( Y" y4 Q
`.get(url)`
6 D- M: g% b4 u3 |1 J/ B$ |3 q. | `.end((err, res) => {`2 V8 i3 f7 M, c$ H! v4 d
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
1 h( A: d, J/ O5 q# K `$(``".course-item"``).each((i, v) => {`
' ]0 F! n d4 n1 N3 } `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`+ U4 |8 ~ T8 m6 _2 o
`const obj = {`
7 y* M1 K3 |; r$ @5 ` `imgSrc : $(v).find(``"img"``).prop(``"src"``),`' A7 J4 h- o3 {, p& ^
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
7 j5 h8 x/ f# P: q% A' ] `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` K0 v( {8 i& a- N7 r
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`1 S# }0 P [+ `) f* T- m3 a
`};`- L- f8 M" s" ^/ g1 j
`console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`+ I" R- v* Z$ q) }. d) I- x
`arr.push(obj);` `//把对象放进数组里`+ m" @) K* {. \: `8 ?5 J
`});`
3 O7 X( n' ?' |9 L* {! A `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`
' n$ C4 D5 @+ M `});`
$ _) L$ d5 @2 D8 h( N 以上就是本文的全部内容,希望对大家的学习有所帮助
w7 _5 [+ Y% U, {2 {" M
V* h* Q( z3 T! X" p
$ p# i6 V9 Q; J% p1 F; [! A9 q8 g2 {0 R! {& s
9 b+ q! f5 m9 | U/ p+ s+ T) V u
|