|
2 C" i: e* C3 U. E7 x3 _( \4 j+ v) m
Koa -- 基于 Node.js 平台的下一代 web 开发框架 ! t0 A" \7 P- R" Z+ I' A
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
6 ~5 ]4 _; _; ]; A k 英文官网:http://koajs.com
! @5 s9 K. v: V! t6 X: D 中文官网:http://koajs.cn ! g# p; q& R m% {$ r: d; }
1.koa
3 g" V8 P% Q b& ? 安装koa包: npm i -S koa@latest " C. k# s% v3 O' q$ k
引入: const koa = require("koa"); 实例化对象: const app = new koa;" |& B( ^* l! v4 L/ U! j* p
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 : ^9 R3 x% c/ H! h" @
use()函数中必须使用异步 async; use可是调用无数次; 0 |/ H0 w+ B; B0 ]7 \% q
其中有两个参数:
1 f/ q {, e3 y2 l+ ^0 `$ W a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 / k0 H5 \' h. u8 ]
b)next: next(),将本次控制权交给下一个中间件。
/ @, }; ]3 V( M# h. f 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
% ~! T/ N, A2 c) a7 R 1. next参数的使用demo
X7 F, p0 j h- x" e" S; t `const Koa = require(``"koa"``);`
$ W- [) z' n1 R$ g E5 i$ U \ `const koa =` `new` `Koa();`+ x9 Y! a/ U$ j/ {% b
`//中间件1`& ~3 \1 I2 c- G0 s8 p h. x
`koa.use(async (ctx, next) => {`
# x" l! p. F6 H4 E% D! x `console.log(``"1 , 接收请求控制权"``);`& k( x' u. w$ B9 J, g
`await next();` `//将控制权传给下一个中间件`
* v$ ], ?: e( n+ E3 l7 V- D% { `console.log(``"1 , 返回请求控制权"``);`2 v4 r1 p) \& J* M; ?) N
`});` `//将中间件注册到koa的实例上`
J( j" }/ ^$ Q4 D) j v `//中间件2`
' U c: I$ T0 ?5 \ `koa.use(async (ctx, next) => {`- h0 T. ?8 P0 }( k' Q5 A. d n
`console.log(``"2 , 接收请求控制权"``);`
1 w6 j8 ^) u! V) r3 `2 N- ?$ I await next();`% k7 A$ j' ~4 D5 d% O
`console.log(``"2 , 返回请求控制权"``);`+ V0 r1 J- t* A0 q$ R l7 }6 v
`});`6 h6 c W9 @, c4 O' e, g
`//中间件3`$ V: }5 [5 R$ H# Y; N C
`koa.use(async (ctx, next) => {`# o. F6 n. I. b2 e: r, t0 M& S
`console.log(``"3 , 接收请求控制权"``);`0 Y5 z1 Y& h) n4 V& {
`console.log(``"3 ,返回请求控制权"``);`
# }& B( G* p6 v `});`6 f$ G% _# Z) _9 @4 O
`koa.listen(3000, ()=>{`
1 ]6 \8 M! r; S `console.log(``"开始监听3000端口"``);`8 `& I$ l- [( N m8 k8 ^
`});`
% U) y$ F$ s* }% J 注:当中间件中没有next(),不会执行下面的中间件 , x. U9 J1 _9 @2 b
访问localhost:3000的效果图;
0 J& f1 _! f( Y3 H 5 G3 P% n- j" _) _, `0 b3 g
注:会有两次操作是因为图标icon也会请求一次 - ~( E/ ?' M- B, C
2.ctx参数的使用demo
0 l' {3 ?. j4 ~5 m; Q4 g Y ^ `const Koa = require(``"koa"``);`2 _6 `6 j! O/ r& T" f8 _
`const koa =` `new` `Koa();`; G! V% J" C/ B* D4 m
`koa.use(async (ctx, next)=>{`1 o2 @1 |9 g+ g0 M9 @
`ctx.body =` `"body可以返回数据,"``;`7 V4 V" d6 r6 i8 [$ V9 b: R
`ctx.body +=` `"可以多次调用,"``;`
$ {: o3 d) m2 [4 K' \ Z+ J, S$ O `ctx.body +=` `"不需要end()"``;`
9 C j K1 c/ D; x `});`5 U* i0 H, Q y5 R& ?- W2 y5 q+ r
`koa.listen(3000, ()=>{`
/ h4 Z9 g; t1 N `console.log(``"监听开始"``);`
' J, L3 V9 e+ f' v3 Z# w8 r `});`
) P2 W2 l& N5 B/ G" ~& z+ H 效果: 6 d9 g( k# M3 P* B" I
, d* j3 L5 A# `+ G/ d6 |
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type + j6 ~- p6 u; x* `/ T1 m: E
`const Koa = require(``"koa"``);`2 i7 u6 h8 v' y
`const koa =` `new` `Koa();`
9 h( n0 x6 _2 w1 j `koa.use(async (ctx, next)=>{`
" D& G3 Y5 b" `( J$ y# I: I0 V0 y `ctx.body = ctx.url;`- d' v5 A7 ^! e" g- x
`ctx.body = ctx.path;`/ s( \% c0 B" ^' J% }7 m* g
`ctx.body = ctx.query;`5 J3 _7 Q8 [* m* D' D
`ctx.body = ctx.querystring;`) p3 } P. c: s* U E- e& g6 Y P- R! k
`});`% }( N$ R4 v, v2 U9 [5 C8 c
`koa.listen(3000, ()=>{`% A! P8 E) f7 D0 h
`console.log(``"监听开始"``);`, T0 m) A, R# }. |
`});`
0 `. G' {, t2 o2 _6 g 访问http://localhost:3000/path?name=sjl&age=18为例,效果图: 4 @3 e$ |3 Q2 v9 d% B
1. url: 整个路径
9 b; t& e0 `0 s4 p1 L+ \$ O+ q
6 _* U, y# `/ k! [8 O+ e8 X( D 2. path: 非查询部分
/ y' N" \6 S4 n' ?& l5 }0 C
4 r/ e2 G# X! p! b. g. Z 3. query: 将查询部分转为JSON对象
$ o3 O# [3 {9 Y' Q+ x/ X$ F1 V8 s0 c
* M% B, ?4 {3 I- q$ m 4. querystring: 将查询部分转为字符串
1 Y5 F" X2 R, [' f+ v4 H9 z
9 O! Z& S0 V6 k 5. ctx.state ,ctx.type 表示状态吗和类型 ' J- g4 H4 }7 y9 f3 X
2.简单爬虫练习
* l% ?* Q& M; u' Z 安装request,cheerio模块 ; a4 }( X3 e1 r2 y \% s- Q
`npm i -S request: 请求模块`( e( T7 r$ s) Q4 K0 _+ o
`npm i -S cheerio: 抓取页面模块(JQ核心)` ) s/ v' s' x2 B8 Y+ l8 n) m
抓取网页数据案例(随机网页) ( g- l0 J- C/ F
`//导入模块`; G9 P& N. T. s$ U
`const request = require(``"superagent"``);` `//导入请求模块`
' b! A7 |1 b; e `const cheerio = require(``"cheerio"``);`& J0 x* k+ u/ W9 U" [* d* Z
`const {join} = require(``"path"``);`& f: Z- ?1 Y) }3 ]; L0 A3 U2 o- d: B
`const fs = require(``"fs"``);`
! W7 F+ N( u' h- `6 _- q `let arr = [],` `//存放数据`
6 |; [7 F# s, \' {2 f4 E8 D: \' K `reg = /\n|\s+/g,` `//replace中使用`- ? G& n; y( V1 C( k! Z8 ^0 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/)"``;`
9 S# n! @9 K! ?7 I, a `request`
& A5 y1 v0 ?9 x4 J `.get(url)`% C1 Q5 g. o0 u" M3 J# W
`.end((err, res) => {`
/ D4 ^! i3 r$ T+ T5 H `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`! B+ O* C: Z5 J; p) P
`$(``".course-item"``).each((i, v) => {`" ?( Y+ B: i& o
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`* F8 `% O. n, d' [: R
`const obj = {`# w7 ]' f+ h7 D6 O7 ]
`imgSrc : $(v).find(``"img"``).prop(``"src"``),`
5 j0 T: J' Z" j7 j S6 ^ `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
) q! J* \! |. Z4 c9 X8 { `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`, K& c2 l2 k3 B
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`. Z% X2 g! C+ D3 V q) l1 z2 y' R- }
`};`
$ M( a! T3 K3 S( B& w+ R `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
+ R+ y- W o& _8 N5 E; T# e `arr.push(obj);` `//把对象放进数组里`
9 j( I4 F; n2 s2 F: m' a `});`
1 Q0 }4 r+ g1 P% | `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`. b' g2 X6 Q) K1 i" x6 m: ]* S' `
`});`
5 F# u" w9 }. ^$ S 以上就是本文的全部内容,希望对大家的学习有所帮助 ; V+ p! S/ E5 d2 N/ {/ D/ ^
! r0 x# a8 C" `2 U$ Q
8 l p8 K. ]7 p4 s
% n8 j0 g- ]# o# B G9 c. r ~, e5 J; d% l- B. j( h
|