|
2 c# a. l5 \! D1 Y8 a. s Koa -- 基于 Node.js 平台的下一代 web 开发框架
9 F& }, r4 }, D+ J0 C koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 & d/ r' ^0 O+ B! G
英文官网:http://koajs.com
/ V1 i6 J8 L2 e3 E 中文官网:http://koajs.cn 1 ~, U. S% v. f `' S$ [( w% _1 H
1.koa
1 t; k/ s; Q# E7 W 安装koa包: npm i -S koa@latest
+ T# f' C* y: I9 o& |/ w9 f- ? 引入: const koa = require("koa"); 实例化对象: const app = new koa;3 A& u, {- Q5 O$ e
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 5 ^6 v8 N; y8 x) E: b' x
use()函数中必须使用异步 async; use可是调用无数次;
6 x7 T) _5 Z- |" L, Y 其中有两个参数: $ [* ]9 o' K- g0 O. U
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 2 i, Q3 A Y+ N0 m6 c; i/ V: J
b)next: next(),将本次控制权交给下一个中间件。
. A/ c. Y0 I/ _6 m0 m 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
1 @. D0 y5 l3 r! } \5 a 1. next参数的使用demo
. t6 \! p$ D/ ` `const Koa = require(``"koa"``);` L2 n1 p$ i" P7 Z8 M' r) j& ]2 I
`const koa =` `new` `Koa();`
$ x% {8 {) ^" g! o+ L0 I( F `//中间件1`
/ _# P. z; T/ ?; }2 @- | `koa.use(async (ctx, next) => {`
& Y& C! Z* v& [; b/ d0 M" u; l' _ `console.log(``"1 , 接收请求控制权"``);`5 O: k: B1 J) n" I( T
`await next();` `//将控制权传给下一个中间件`4 z! C5 w- o% E3 P2 D
`console.log(``"1 , 返回请求控制权"``);`6 b i% h) r* t; e* E
`});` `//将中间件注册到koa的实例上`
( i( V9 h8 r3 [ `//中间件2`
0 n; i. I1 h- u0 p V `koa.use(async (ctx, next) => {`
8 j8 n5 ?3 T! Q. Q; }- l `console.log(``"2 , 接收请求控制权"``);`, c1 h. I: K. ]3 T+ I6 y* v5 e7 H
await next();`
d" X5 T" Y' u5 |/ _/ v `console.log(``"2 , 返回请求控制权"``);`
# P9 w7 N8 f8 Z `});`
( e! C) G3 L) d: S; f7 r `//中间件3`
+ v0 b k1 g t1 m4 i$ u) d* F `koa.use(async (ctx, next) => {`% `6 G5 {9 }" I* S1 z
`console.log(``"3 , 接收请求控制权"``);`
" U7 q( W% a5 J. S `console.log(``"3 ,返回请求控制权"``);`4 f$ y: ~5 z. b+ U
`});`
% h2 b3 l' ?1 o8 ] `koa.listen(3000, ()=>{`/ w8 G! @" }) J7 u
`console.log(``"开始监听3000端口"``);`
' L( n* E2 J+ e! C/ P `});`
4 L/ i' p9 C2 T) |; R 注:当中间件中没有next(),不会执行下面的中间件
% U- ?' B) Z1 b" b$ c0 ^ 访问localhost:3000的效果图; z/ a: U& _" N9 r2 b6 n7 _$ ~
' u2 ]* J" B6 m2 G' f 注:会有两次操作是因为图标icon也会请求一次 2 [/ s5 l, Q% h$ S: m
2.ctx参数的使用demo 2 }; b0 V- e% }2 J6 }* i0 @
`const Koa = require(``"koa"``);`
5 _7 z i* [& }! Z, g1 {) v `const koa =` `new` `Koa();`5 J& _! y1 u1 s; c6 J
`koa.use(async (ctx, next)=>{`0 F5 I* N, E7 x6 Q
`ctx.body =` `"body可以返回数据,"``;`0 T7 f$ e( o. y0 q0 H& D
`ctx.body +=` `"可以多次调用,"``;`, ^& N$ F; c6 ]% {+ i
`ctx.body +=` `"不需要end()"``;`" f" {7 j' h8 Y4 w4 C
`});`
8 |& p. e6 |4 z& t4 I `koa.listen(3000, ()=>{`, y( _. r4 V& G% d2 A+ D
`console.log(``"监听开始"``);`4 c( m, a# {# p- e9 O1 L* z1 o! K
`});` " u4 B- t7 K% A( ^- g
效果:
( T9 |3 |8 F( H; G4 l: r3 f- B/ \ C7 c / }. }5 w7 a- Y3 |" f& u/ z
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type 6 i4 Y& Z. \9 W [8 Q
`const Koa = require(``"koa"``);`
4 T5 w2 {( U* ^0 D; W+ w m `const koa =` `new` `Koa();`8 n: K& M; S: @. H$ p
`koa.use(async (ctx, next)=>{`) y8 T" U; R6 ^( k' F
`ctx.body = ctx.url;`
3 P3 t& o' o2 A& x3 e `ctx.body = ctx.path;`
8 d' `) u; I& ^6 S9 f `ctx.body = ctx.query;`+ N* l6 O' g0 N7 x$ j, i' A3 H
`ctx.body = ctx.querystring;`# s$ L5 K2 k$ T5 J1 Y& J
`});`- [; f/ E9 d; j- R" S( S! [. E# S+ ?
`koa.listen(3000, ()=>{`
& |- \: C0 D' v% p `console.log(``"监听开始"``);`
; `. j2 n" w( n; _ `});`
) Z9 m5 P0 m9 R2 @1 A! c" {' J 访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
8 _) s, I: q0 _ 1. url: 整个路径
) p4 [- l. p4 r3 r. q+ ?: a, Y3 u
M5 q$ {$ s0 x& t# X7 | 2. path: 非查询部分 : V+ [2 S! ^ _( F5 m6 R
7 ^2 I5 y+ X: I& d 3. query: 将查询部分转为JSON对象
( Q1 b( b. y3 h' @ b& I
4 @$ j( t! m; K/ |, ? L+ B1 q 4. querystring: 将查询部分转为字符串 6 c' J+ a5 c* |# E! a- x- w" L- u
5 b0 t+ P# E: W y8 s" D 5. ctx.state ,ctx.type 表示状态吗和类型
+ w% V u- m0 B( P4 ~8 M. \ 2.简单爬虫练习
9 G9 Q4 D/ F8 y8 j6 M$ p: w6 E- e7 b. e 安装request,cheerio模块 ; D, ?5 ^ T( e7 {6 N* F8 t3 j: d( b
`npm i -S request: 请求模块`4 l: _9 [! a( o! z( u {) j
`npm i -S cheerio: 抓取页面模块(JQ核心)` $ C7 N/ N7 s; G* ~% A
抓取网页数据案例(随机网页)
' v; W9 ^/ \! O, l) @ `//导入模块` G4 E! T0 x4 Y5 Q
`const request = require(``"superagent"``);` `//导入请求模块`) a/ R: T) g; S- W& H' j
`const cheerio = require(``"cheerio"``);`' z' |5 ]- D v1 r: b- Z* h* i
`const {join} = require(``"path"``);`
( b3 m7 A" ?) ^7 @! x$ r# B! R `const fs = require(``"fs"``);`
' O! Q+ _% S E9 o0 { `let arr = [],` `//存放数据`, q- J3 i; }8 B% i* P) s) c8 A) J2 `
`reg = /\n|\s+/g,` `//replace中使用`
. f! `! I3 E& F B `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/)"``;`
( g7 Y% _. q6 _7 Y1 z/ L `request`
4 g, C0 q, h& D6 n! S! R `.get(url)`) U5 W/ J: M, l, X7 L
`.end((err, res) => {`
0 r. @; m' }6 D& ^ `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
# ]0 q+ y7 g- ]% B, t7 D `$(``".course-item"``).each((i, v) => {`; J$ E! i* S% q6 V% N( o
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
9 M8 B) F. Y+ K* [7 k* m! M1 f, O2 T7 ] `const obj = {`: C- g4 G% c b8 J
`imgSrc : $(v).find(``"img"``).prop(``"src"``),`* O2 K& l1 N( Y
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`! P2 ^$ n( |/ Z. o* B8 }
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`; v& l0 D) V, B& y; {
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`% c0 F+ r" x4 E1 z1 U. ?$ l
`};`
2 e' v0 I5 x' C; S0 i9 B4 b `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
& X0 a' w( U' b3 Z1 g8 ]( m `arr.push(obj);` `//把对象放进数组里`, [) }& u6 K4 {$ \/ a$ A; j( Y4 I
`});`& i* a& j5 ?4 j6 O. _" ~+ K
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`* J6 @/ m% X! c3 z) z
`});`
p9 N3 t% J0 y; H 以上就是本文的全部内容,希望对大家的学习有所帮助
% d6 P- P# f; k: E
0 J7 z( E2 c; c1 [5 y' o
6 x, J6 ]: ^- y, x) [
7 k4 r) L2 U9 l, ^2 B4 |5 N) F r G6 q! A
|