|
2 E; ^: q" s5 D( a4 I Koa -- 基于 Node.js 平台的下一代 web 开发框架
# p# ?9 j8 P5 U4 v! @% d# I koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 0 u8 }2 x7 F& Y* p
英文官网:http://koajs.com
2 G/ K7 T3 M$ {& J3 i3 f2 M% u 中文官网:http://koajs.cn ) l) G, U% b3 A, J3 ?7 ~# I
1.koa
6 G& v k: A, g0 l$ o' e$ o8 I: ] 安装koa包: npm i -S koa@latest
7 z0 L. Y; n5 \& @: L5 A; i: \! C 引入: const koa = require("koa"); 实例化对象: const app = new koa;+ |4 ^" E/ c; H0 M! f/ _
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册
, s. @7 z, Q& W use()函数中必须使用异步 async; use可是调用无数次;
9 T6 Q: J8 z e& g. t8 N6 W 其中有两个参数:
# F' b: V" l8 E" V/ H8 v a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
8 u- \9 i. Y5 u: e b)next: next(),将本次控制权交给下一个中间件。
4 e+ d! X9 f) m7 [ 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 - w6 Q0 x/ R% b& g2 W3 ~5 X
1. next参数的使用demo 0 [4 F) V" }5 j
`const Koa = require(``"koa"``);`
% H4 v2 w1 J$ } `const koa =` `new` `Koa();`
* `0 X' c- m& g% r; w$ X5 }% l `//中间件1`5 l, m- }% X. @; X1 }; `" g
`koa.use(async (ctx, next) => {`: S7 ~2 t. }( O5 x1 Z1 X
`console.log(``"1 , 接收请求控制权"``);`
8 k0 }. Q4 H" G1 t1 z `await next();` `//将控制权传给下一个中间件`
( W4 A8 \1 x# Y) X e# U `console.log(``"1 , 返回请求控制权"``);`
3 y2 E: }8 w: C1 J `});` `//将中间件注册到koa的实例上` X1 G F9 P! n- ^9 V' l( X
`//中间件2`6 w5 r _, C0 I
`koa.use(async (ctx, next) => {`
8 C9 o3 r. f* X+ C2 ^( G6 {" A5 p `console.log(``"2 , 接收请求控制权"``);`; y3 s! I) O8 v5 j
await next();`5 P. {, I) ?/ M Q% i4 s X3 U) _
`console.log(``"2 , 返回请求控制权"``);`7 ^) T! K7 V. o2 A5 Q7 o" K7 Q
`});`* _' U# y5 f J; `' H! ^6 ^8 z$ s8 k
`//中间件3`- `! \9 ?, M9 l8 j [8 w2 v
`koa.use(async (ctx, next) => {`
& f, P4 ]0 l! j& C& t- i# l7 Y/ p( h `console.log(``"3 , 接收请求控制权"``);`
; r+ ^ j% f( k- v `console.log(``"3 ,返回请求控制权"``);`7 X# I u3 v C$ [# Q4 k& t1 y, P4 S2 _" v
`});`" ?, |9 T- q8 \7 L% L# B
`koa.listen(3000, ()=>{`
/ C' R. U' [+ @2 w5 X% M6 g1 j `console.log(``"开始监听3000端口"``);`
+ y" E/ ~: p$ y" m" E `});`
7 z! U1 u3 | B) S$ ~# _8 _7 { 注:当中间件中没有next(),不会执行下面的中间件 / l* @+ {$ r$ q. X4 h7 M( N
访问localhost:3000的效果图;
( R; M; A- r r8 Y$ Q' T / i. B2 U s7 K( r% k, z4 ~
注:会有两次操作是因为图标icon也会请求一次
( M( p/ D6 m8 J' O* a: ? 2.ctx参数的使用demo
- H, X3 i; p0 ]6 O' c* @ `const Koa = require(``"koa"``);`
' X8 O, ~. D; D `const koa =` `new` `Koa();`
3 z q. y/ T7 V `koa.use(async (ctx, next)=>{`+ U/ S6 S7 a l/ |; ^7 v
`ctx.body =` `"body可以返回数据,"``;`" Z# \/ }; _. O @. t
`ctx.body +=` `"可以多次调用,"``;`& j, C/ l* ~* G+ Q/ R' R
`ctx.body +=` `"不需要end()"``;`
0 M5 ]; h; k( I: T, Y `});`& O7 k2 G: z7 _- s* y. l
`koa.listen(3000, ()=>{`4 S$ M# ~1 n3 f
`console.log(``"监听开始"``);` ~; d; o M5 W! E' s3 \- S" j t
`});`
! h' I4 x& a* [. _8 C 效果: + ]' w% N: V8 E/ m# d$ x8 N
8 |: I" t1 ]: @0 l: d1 v- q2 P& _ ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
0 I, A. e8 A' ^& A2 d& e m% G+ `& M `const Koa = require(``"koa"``);`2 I# ~ Q5 u- e! R9 u3 I- L
`const koa =` `new` `Koa();`- U- v6 K6 C! \1 U
`koa.use(async (ctx, next)=>{`
% L% c' c4 N* n& C. R7 O1 e' j `ctx.body = ctx.url;`# a( w# A& _2 \
`ctx.body = ctx.path;`& ^* X% x V5 _+ D% q
`ctx.body = ctx.query;`
2 n. Q2 I( m( D! G `ctx.body = ctx.querystring;`
! z R) r$ Z' g& [. _7 c' g `});`
1 c6 g# v0 d! o+ c4 Q `koa.listen(3000, ()=>{`9 O5 Z0 M0 b0 s6 T
`console.log(``"监听开始"``);`
, S* X* g9 D$ i% g6 n( ` `});` [+ b. n. k# c. ]5 a& p: |
访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
: x( q" u. y# d% R/ k: U 1. url: 整个路径 / U/ I# I+ H& ~ F7 L
; T2 o9 F9 _: o' h7 Y, B 2. path: 非查询部分 0 R" W9 T- d$ o$ J' o9 }
+ o Q( ~8 g) }; X7 f- t
3. query: 将查询部分转为JSON对象 3 d( p' X2 u8 f3 p3 _& l" `
) u: J( l& } J
4. querystring: 将查询部分转为字符串
: [. j! {" I4 p$ D+ y5 s
' l9 c# s+ z% I' P7 K/ x h1 Z 5. ctx.state ,ctx.type 表示状态吗和类型
( q2 q6 P3 Y) Y" O7 Z% w 2.简单爬虫练习
: Z3 F5 K( |* g4 f L. h3 l; O4 W0 ` 安装request,cheerio模块
, x* e$ Y2 D/ _ `npm i -S request: 请求模块`0 @$ X0 i6 |) [) y( y
`npm i -S cheerio: 抓取页面模块(JQ核心)`
$ p! d4 E% g" J8 Y& h& v/ s V" G) S 抓取网页数据案例(随机网页) 7 h# G7 C4 o/ e
`//导入模块`& \& L0 M! ^; \9 ]. @
`const request = require(``"superagent"``);` `//导入请求模块`
" y- H6 r( f* Z# O( {( ^% j `const cheerio = require(``"cheerio"``);`' R; f' n0 {+ k- \9 O! i! f% s
`const {join} = require(``"path"``);` T; k( e1 U3 P, {0 S( d! y
`const fs = require(``"fs"``);`
$ Q1 S! |' i( [0 k `let arr = [],` `//存放数据`2 ]( [' d( t8 F8 ^" \$ j- \7 I
`reg = /\n|\s+/g,` `//replace中使用`
1 c/ e% ~$ M) |. }7 i `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/)"``;`
8 w! ]6 K+ d' Y# i, [) L `request`
! o t8 e) Q: [& I: _8 ` `.get(url)`
/ t4 \% }' s' }% g) u `.end((err, res) => {`) t% N3 f% r& e: q5 V* p
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
( ^" B; ? y/ V7 b6 `4 F* P `$(``".course-item"``).each((i, v) => {`
. W0 F- i' A! k1 S2 W1 T' C7 W `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
0 ?% [8 I3 ^, F3 q: R `const obj = {`
0 @) Q( ?) b% w. E* s2 w& l `imgSrc : $(v).find(``"img"``).prop(``"src"``),`
. J' r$ u6 g, g. V6 [ `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`7 U' N# M3 Y; J. T9 k, A
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`1 V; J: Y: ]% A! N$ n. P
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
8 L4 B4 j& x4 r: j( { `};`
6 K# c0 m4 c" m" r4 } `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`9 ?% l" o+ r3 \ q
`arr.push(obj);` `//把对象放进数组里`6 ^. @5 A b, ^; S |! O! N$ |
`});`
! ?3 ]% V2 t+ W( J' j [9 h9 E `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`& s. R5 K. c' p3 y' O
`});`
' a2 D/ p, n+ ?) ` J6 r" {6 w 以上就是本文的全部内容,希望对大家的学习有所帮助
9 c2 j( }2 ]+ Y3 [- {4 S6 E) V
8 b6 J2 G1 {( C z0 b7 P3 N8 ~
- i( Q" K3 J6 b P+ B. V( g4 b t7 [
4 b2 f9 ?0 f% Z9 ]/ G
( p5 P: z4 \0 Q) w s |