|
* ^+ p/ \9 V- U" c
Koa -- 基于 Node.js 平台的下一代 web 开发框架 # ^$ g3 L. l2 z5 r5 E% S- W: E
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 & s' r$ i" x. U" K N
英文官网:http://koajs.com , X l; o4 `% S
中文官网:http://koajs.cn
" b( Q7 v+ Q4 C: n" |: [2 C 1.koa
: G) M6 l, g' K" Z/ [/ T$ S) ^ 安装koa包: npm i -S koa@latest + k+ D2 I% z! j" [; s
引入: const koa = require("koa"); 实例化对象: const app = new koa;% i% B4 M1 J7 m+ D2 y
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 . A/ ?, Q* z3 {& u G" D
use()函数中必须使用异步 async; use可是调用无数次; ( K; L# J! j) f. N# x' z8 Y
其中有两个参数:
- S9 ] P& p* Z4 f( J8 z a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
& b1 R$ J; ~3 g. A; J% [1 n/ k+ l b)next: next(),将本次控制权交给下一个中间件。 2 ^" E% C* ]( D5 o
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
' D6 k; a" m% U5 g) J, e 1. next参数的使用demo 7 @* @+ G8 Y; |, h) @
`const Koa = require(``"koa"``);`, z$ C! L7 T) J' O/ r8 n& A$ u
`const koa =` `new` `Koa();`/ R0 U }/ J. m
`//中间件1`4 G% J1 B$ P( y
`koa.use(async (ctx, next) => {`* }7 F8 V! P* G% @* A4 A. @2 Q" l
`console.log(``"1 , 接收请求控制权"``);`
3 v3 B0 {1 G7 T' @ `await next();` `//将控制权传给下一个中间件`
1 k9 _. S6 @9 L* ~2 v z, ^ `console.log(``"1 , 返回请求控制权"``);`
9 l) n7 `) r9 k: I D0 P7 d `});` `//将中间件注册到koa的实例上`
( W7 _( `3 @5 V: `+ w5 Z `//中间件2`
9 V, H% z0 I% |/ V2 u. f* H `koa.use(async (ctx, next) => {`
; o& W" E4 n0 W- L& u' v( `% T3 Q `console.log(``"2 , 接收请求控制权"``);`! ^% z. j- i# j, X
await next();`6 {4 v3 Z0 I- j9 _4 ]; H
`console.log(``"2 , 返回请求控制权"``);`) v8 E7 t ~7 z
`});`
7 ]! ]1 H* }! x" z: R" ~ `//中间件3`! D1 K0 q1 A$ d! u
`koa.use(async (ctx, next) => {`
1 W, B% S i0 z8 g' r6 J4 p `console.log(``"3 , 接收请求控制权"``);`
/ ?' a" g A5 F `console.log(``"3 ,返回请求控制权"``);`$ g& ^* N; J# p' a1 a! j
`});`4 V6 m0 ~( u. F2 G( I/ h
`koa.listen(3000, ()=>{`
3 Z* k p$ Q% r! L4 P `console.log(``"开始监听3000端口"``);`
* A1 ?! a) }- m/ {" g, z! D `});` ' \( S- J4 b( f
注:当中间件中没有next(),不会执行下面的中间件
8 R8 b+ T* R7 J; w! Z- T9 f 访问localhost:3000的效果图; 2 D6 B6 O* c! |9 y
# V9 u( [& D% R$ x 注:会有两次操作是因为图标icon也会请求一次
2 g2 }5 `, d4 f* V6 S* {( T 2.ctx参数的使用demo
% A1 s6 B9 g0 y' N `const Koa = require(``"koa"``);`
2 p' E5 {2 f8 ~ `const koa =` `new` `Koa();`/ p( f7 j1 |! I& Q5 i
`koa.use(async (ctx, next)=>{`* `2 y9 ]4 M& D9 O
`ctx.body =` `"body可以返回数据,"``;`
1 v' Q2 Z8 u* P: e0 L/ p `ctx.body +=` `"可以多次调用,"``;`) w! b' T; H) c
`ctx.body +=` `"不需要end()"``;`
0 o0 Y9 V: [. Z `});`
. H5 E3 {. l0 g4 t# T3 X `koa.listen(3000, ()=>{`* M: @ I5 F( |; z; }2 x, Z) k
`console.log(``"监听开始"``);`
7 N3 X- \! o5 { `});` 5 X2 t' \+ |; q) |1 \1 N A4 K
效果:
% W1 X) p/ |, k/ ` |# [- i
4 ]7 G& C' p" ~6 d6 b; `' N ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
3 p }. c: v5 p! }+ [% l/ v$ C `const Koa = require(``"koa"``);`
9 u# m2 i( r6 n+ P+ ? `const koa =` `new` `Koa();`
' @/ G d l( j `koa.use(async (ctx, next)=>{`
/ ?0 X5 M R. q) I1 T: D `ctx.body = ctx.url;`
: u9 H: Q/ s. w `ctx.body = ctx.path;`
) s* @- {. a$ r) a3 F; ^ `ctx.body = ctx.query;`# e9 Y& u2 ]9 w' i
`ctx.body = ctx.querystring;`
0 K! w" j! t2 o9 D9 U `});`: ]& o3 D( J7 t4 U. U
`koa.listen(3000, ()=>{`
8 [1 O6 `" h0 I1 D o: d `console.log(``"监听开始"``);`0 k% z3 u" m# V& g4 H% C
`});` . j3 j" u/ X }7 M$ ^2 \5 E
访问http://localhost:3000/path?name=sjl&age=18为例,效果图: % x% R2 F" V! O, A4 H' L& b% ]3 a
1. url: 整个路径
2 j1 G7 E8 \; T0 } x# B0 L- m . V2 T t4 Y y7 U9 ]
2. path: 非查询部分 5 f+ |, i$ `0 `" j! J1 k
" d* \7 X7 u3 w 3. query: 将查询部分转为JSON对象
% f6 e& O; s. P2 N/ P/ V
/ E5 N. s# ?( `# w 4. querystring: 将查询部分转为字符串
1 r: K8 n) A& G6 k
4 M% p- z/ S$ h5 n- [: e 5. ctx.state ,ctx.type 表示状态吗和类型 2 V3 {& |- v- P1 V! T
2.简单爬虫练习
9 T8 j( G3 o# [3 P3 S5 n 安装request,cheerio模块 . }& m i* w1 {! |; @
`npm i -S request: 请求模块`
& e. H. |4 `3 M7 k5 d7 Y `npm i -S cheerio: 抓取页面模块(JQ核心)`
8 L# Q" b+ }+ r4 t4 H0 a, h5 g 抓取网页数据案例(随机网页)
3 h4 I( D( Z2 i% k. u7 M* b, l9 B3 Y `//导入模块`6 [* P1 F+ y; n! Q& V. A
`const request = require(``"superagent"``);` `//导入请求模块`
4 p5 j! f7 o+ |4 ?/ _8 J! c `const cheerio = require(``"cheerio"``);`
" u. W0 d5 V9 Y `const {join} = require(``"path"``);`
- f* j/ A& }+ l9 e9 J0 W `const fs = require(``"fs"``);`2 b0 v) F/ Q% I: @
`let arr = [],` `//存放数据`
1 a4 N5 k3 Q% P8 R `reg = /\n|\s+/g,` `//replace中使用`
3 a6 b. x3 B8 E9 o. ~- [ `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/)"``;`
: t [$ Z$ i( d: L; D( @ `request`
( d. i, z J9 K9 U6 p1 Z `.get(url)`
- o7 d" m8 ^# Y* L( O0 ] `.end((err, res) => {`" _7 b3 r! ~ k$ s+ ^& m. E* l) s& l
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`, M: t1 U6 S3 s9 k! |4 x: c
`$(``".course-item"``).each((i, v) => {`
" T+ H( V8 z; I6 { `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`& A' v( r! \* b6 {- m3 H# C, J0 k6 k" Y
`const obj = {`
" x3 d. ^, j0 q. | x8 c* Q: r9 w `imgSrc : $(v).find(``"img"``).prop(``"src"``),`
5 U/ r: A; K8 _/ X, t$ E2 t& e `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),` m( \) Z7 u+ S! I. A1 H
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
, L: o* C( h- \2 l! N `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))` [2 X$ @# l: t/ X
`};`
* ?4 ?- L9 q3 q4 d `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`, z! m, A5 Q" V& _& `1 [3 a: ^
`arr.push(obj);` `//把对象放进数组里`
4 @2 a) x) K: e1 U( z `});`
7 N0 c: q- O; Y' V) L `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`1 Q6 @) H- q7 G* l& |
`});`
4 Q$ S' W6 g$ f' n5 i+ y( G* x 以上就是本文的全部内容,希望对大家的学习有所帮助 & U+ R0 F3 Z4 k2 h- {
9 `, B2 V2 C' F, G
# D$ M) i+ w+ l: n2 t& { v9 I
$ J6 X) [; D! P5 o* V
|