|
& q2 q) ^4 V. i7 B4 s, d0 i7 w
Koa -- 基于 Node.js 平台的下一代 web 开发框架 ( q7 {% t6 [; t, e
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 8 N4 B% [7 M; y ~4 H1 n
英文官网:http://koajs.com # a! C3 r; }1 A7 M- x
中文官网:http://koajs.cn ; A0 j. B- }3 v: W& c
1.koa
8 E, Z. C, ?9 |7 f( g ~ 安装koa包: npm i -S koa@latest ( I& G# j1 U, C# O! [
引入: const koa = require("koa"); 实例化对象: const app = new koa;
) @! Z9 `: ]0 y7 T 通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 , K$ V; o& J% @1 Z: k
use()函数中必须使用异步 async; use可是调用无数次; ; L3 x; d1 _/ n' b% m" Z! p, |9 T
其中有两个参数:
$ q- m& ` M9 b! R: } a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
2 ^: y9 q1 o3 l9 g5 e) ]9 K( l0 N b)next: next(),将本次控制权交给下一个中间件。
" V8 e) X& a+ H4 T5 W/ C6 P 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
0 k2 B5 H9 l& O, K 1. next参数的使用demo ' \; T8 L; M4 b4 ~2 e$ S
`const Koa = require(``"koa"``);`1 j3 |, ^6 ~' L, b. ]' e
`const koa =` `new` `Koa();`. s4 Y! z7 [% [) m. w9 L
`//中间件1`
' ?$ b- g; W! A$ }7 [# p& { `koa.use(async (ctx, next) => {`
5 ?$ T' t3 Q- _. p* W `console.log(``"1 , 接收请求控制权"``);`
. p$ i) T9 J U4 M& V. p* G `await next();` `//将控制权传给下一个中间件`
5 ~8 e( N% `0 K `console.log(``"1 , 返回请求控制权"``);`
. I; r/ L3 [/ i `});` `//将中间件注册到koa的实例上`
3 f5 e7 i% ~$ _2 s4 S: M g `//中间件2`
# ^+ P5 i+ R* G" d `koa.use(async (ctx, next) => {`+ [( i: ]+ g+ U% g: ^' J8 C5 V
`console.log(``"2 , 接收请求控制权"``);`
4 k4 G7 u4 v' S9 W' U await next();`
/ [/ d* T+ _3 L: }4 J& R `console.log(``"2 , 返回请求控制权"``);`
2 r& h+ n4 y2 P, b: w' p5 G0 w) s `});`3 c. N3 p5 m( `! p
`//中间件3`6 C/ K9 O! T B
`koa.use(async (ctx, next) => {`
0 ]; W! W, {( a5 q `console.log(``"3 , 接收请求控制权"``);`' n: Y+ g# X3 x7 r8 m& L2 R
`console.log(``"3 ,返回请求控制权"``);`
2 ^! f$ }: d0 g c7 o! p( o `});`* U: ^. H; {- n+ x' ]" a, y8 d
`koa.listen(3000, ()=>{`
0 t, ?$ g" V5 r `console.log(``"开始监听3000端口"``);`
, @. ?$ h$ a( j8 o `});` 3 `+ ]) I5 T3 D) y" Z# d
注:当中间件中没有next(),不会执行下面的中间件
9 T$ M R: y& D: z 访问localhost:3000的效果图; 2 @* d$ M, Y* A0 m" t" t# ^; A
: z" C+ J) x+ h' R 注:会有两次操作是因为图标icon也会请求一次
, b4 q/ [6 ^" _# j5 i. e k 2.ctx参数的使用demo
' Z( T3 C: a6 y" a8 Q; Z' [" r `const Koa = require(``"koa"``);`( M# U) A$ Z4 _2 `
`const koa =` `new` `Koa();`
6 O4 Y- `8 L8 i8 u) J8 v; X- ` `koa.use(async (ctx, next)=>{`2 L$ U+ X% [$ Y; d3 {/ l
`ctx.body =` `"body可以返回数据,"``;`7 z; m0 s$ `% C" g
`ctx.body +=` `"可以多次调用,"``;`& G9 L& `! m4 [& L% ?* Q
`ctx.body +=` `"不需要end()"``;`; k- N2 b+ D( S5 ^/ w) l7 T
`});`/ a; U* p4 s% {& I
`koa.listen(3000, ()=>{`
0 u" T5 F) f9 e+ A! Z7 }( W: V& x `console.log(``"监听开始"``);`# n( I* d' B+ i" s( C/ M% L
`});`
$ A, Y; K( Y4 S. Y, y3 d 效果: ) e3 \1 V' q, D# J. C
9 V9 r+ H: l" S4 @( Q# T' t
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type * C! p, t( s. j- K& A1 O
`const Koa = require(``"koa"``);`
5 h: z# H5 z6 d. n1 } `const koa =` `new` `Koa();`% x% u3 ~. ]8 k' l0 `" a( j
`koa.use(async (ctx, next)=>{`, {4 N/ S0 l& T* a* L* A
`ctx.body = ctx.url;`! V5 i/ H& X1 u6 n+ b* k" E4 \1 l
`ctx.body = ctx.path;`
) W* E% w" W; r" `: J% l. j# H `ctx.body = ctx.query;`/ X2 r! F( D) |. a+ A, K/ `
`ctx.body = ctx.querystring;`& M* l! ?; z6 e/ h0 A- C
`});`
2 [7 S2 E1 ?; [& z `koa.listen(3000, ()=>{`
+ b% I2 ~- D0 k0 r- I9 l0 M' ~ `console.log(``"监听开始"``);`
% ~) L, ]5 L1 `0 K `});`
. \# f4 Z; _: r M V% A 访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
0 C. p& l. V; r+ L- U 1. url: 整个路径
: T* L2 F; S9 I V5 m 6 [1 j! C. k# I
2. path: 非查询部分
" o) M7 R6 E: v, r: L5 E' ~8 K/ F C , ^7 D, d9 C2 j0 l: t
3. query: 将查询部分转为JSON对象
3 P. F1 A9 w4 b. p
1 D3 a" Y4 l1 ^) G# _ 4. querystring: 将查询部分转为字符串
o) `$ Y4 C [ . v6 _) e, R6 d' x
5. ctx.state ,ctx.type 表示状态吗和类型 / e t. I9 K1 @8 Z! r8 p
2.简单爬虫练习
- ]% ^1 H! x$ T) U* @1 t* A, H' X& h) l 安装request,cheerio模块 W, j0 @3 c+ o0 Q5 O( s
`npm i -S request: 请求模块`
% P2 m' w; D. C \' T% a% l `npm i -S cheerio: 抓取页面模块(JQ核心)` - Y: e) S! q# Q, c5 m" Y* E2 P
抓取网页数据案例(随机网页) 7 b+ ]$ z' ^2 y. l+ r( t6 ?1 |
`//导入模块`5 z, Q2 s+ M# B
`const request = require(``"superagent"``);` `//导入请求模块`5 A# T7 S" d9 f$ E5 L+ ^+ l1 w% H
`const cheerio = require(``"cheerio"``);`* q& G7 ]2 x# o$ U0 D* {4 ~
`const {join} = require(``"path"``);`
, `' ?, x8 a+ I4 A% }+ o `const fs = require(``"fs"``);`$ R% M4 m5 p( F" @) o
`let arr = [],` `//存放数据`
8 M" K l2 r4 q1 l+ c+ H# }# H4 ^. c `reg = /\n|\s+/g,` `//replace中使用`+ l c: Y+ f2 n4 d( 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/)"``;`
( ]# s: R1 s3 R! ^# Z+ H# b: c `request`6 P; }. f h$ [5 S: B1 x! s2 u
`.get(url)`
7 R) r% A. u, T4 {' I9 i `.end((err, res) => {`
3 m- |+ v+ } J/ X6 y) D `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`" _6 w+ U. T6 h) X! z
`$(``".course-item"``).each((i, v) => {`
$ H9 q, t' B+ _ `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`7 g/ e1 W$ f/ m+ _2 y
`const obj = {`
" c, [5 e/ b5 Q) C! l `imgSrc : $(v).find(``"img"``).prop(``"src"``),`2 n; E7 h8 g/ S1 ]& u
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
$ e& p1 ?5 T/ |- i3 I `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`% n7 k2 }5 ^ Q% \
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`/ M# n" X5 `' g- R" w X
`};`
- |: p, r5 s& x) Q, I5 p+ H `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
( C+ d* i. \& R7 c% \7 _. |1 d `arr.push(obj);` `//把对象放进数组里`
6 A+ e) N5 v0 m4 g2 u `});`
6 O8 \1 `$ G/ {, p# d1 U8 w0 C# v `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`' E/ l/ q, D/ I# p" U% R/ H; U& r
`});`
. S- @$ F1 P a3 E/ V8 F3 S* e 以上就是本文的全部内容,希望对大家的学习有所帮助 . `! ]9 F. \ y- A# R
- ~ Y! {) \, j R. T7 a9 y
# l$ O( L4 t& R+ X2 Q: A+ [" _
) w5 n2 x; K8 x$ v# q0 Q8 A4 l: k& d7 M8 {6 R9 h" R/ E4 w
|