|
4 B' X* K3 O2 j. S% f
Koa -- 基于 Node.js 平台的下一代 web 开发框架 % u J2 D& H6 f
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 - M0 ~# ~: j2 T; y! E# y v
英文官网:http://koajs.com , f/ P$ l- U; v
中文官网:http://koajs.cn
- {% i- q: w# ^3 f5 B& I7 v 1.koa
# I) G2 I; w: b/ D 安装koa包: npm i -S koa@latest
8 k/ i9 E$ b2 b8 e6 G3 h4 U 引入: const koa = require("koa"); 实例化对象: const app = new koa;
' S+ h. o1 v( Y+ ]5 e- r. @, ~9 y% W 通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 " p. P' `* R- ^2 K! _6 A
use()函数中必须使用异步 async; use可是调用无数次;
, h# p0 \! {% ~! k- N9 Z1 V; | 其中有两个参数:
& i9 B4 s; U/ b0 @( l H a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
% ~ q, O3 i& p b)next: next(),将本次控制权交给下一个中间件。 / l1 v2 u- k4 j9 s% o' O
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
) E$ A* a J4 I ?' T 1. next参数的使用demo + V- p2 U$ @$ }! [3 b6 r$ F4 U
`const Koa = require(``"koa"``);`
- v, J# ^+ P8 s* e `const koa =` `new` `Koa();`7 g1 h. C$ K/ C9 X) J0 g, D+ |
`//中间件1`
& R7 ]3 e6 T$ W8 o) D; g: L- i `koa.use(async (ctx, next) => {`
! S3 f3 W/ |- v. m. X: L8 L( q# M7 ` `console.log(``"1 , 接收请求控制权"``);`
7 {8 u% P! C8 n% Y2 V- b9 s! u0 @ `await next();` `//将控制权传给下一个中间件`
, o' W- J+ i1 G! ~8 B `console.log(``"1 , 返回请求控制权"``);`. W: C# ] h; e( @
`});` `//将中间件注册到koa的实例上`8 \0 A1 @% p7 \7 `! F/ v
`//中间件2`
& \$ f) n3 r; H! o8 _ `koa.use(async (ctx, next) => {`
8 z6 Q" W8 y) ?5 k6 R* H `console.log(``"2 , 接收请求控制权"``);`
/ r) O6 c! n0 z' J7 i await next();`
9 ^9 h$ U2 K e; B* ~3 E' o `console.log(``"2 , 返回请求控制权"``);`
) ^; D' I& m, ]# w2 h- I `});`
$ v& |; J/ x0 b8 Z `//中间件3`7 ]6 S1 s( a f5 O. O* ?
`koa.use(async (ctx, next) => {`" U9 J; M# }6 w& E5 m9 b
`console.log(``"3 , 接收请求控制权"``);`
, [9 {1 n8 m( l' o; i. y- y `console.log(``"3 ,返回请求控制权"``);`
% W6 s; p4 K% ^: R, z0 G `});`/ q: N) S( ?" F* e7 u
`koa.listen(3000, ()=>{`
. {, ]) M! T b* `4 d8 O, I& A- P `console.log(``"开始监听3000端口"``);`$ Q* ^# n# j) w
`});`
/ c3 v# f1 Z9 ^3 ?# ~ 注:当中间件中没有next(),不会执行下面的中间件
$ J, A9 H4 i( [+ P! N 访问localhost:3000的效果图; 0 M# s# T4 B; L2 t/ v
& g. U8 m1 Y& S% i8 Y
注:会有两次操作是因为图标icon也会请求一次 ( X8 {- {- k4 g& i" C
2.ctx参数的使用demo 5 T* s7 o( k+ Z$ {0 k9 g/ U4 T
`const Koa = require(``"koa"``);`" R# l2 t* B7 h9 {3 ?9 D
`const koa =` `new` `Koa();`. E6 v$ G$ E$ F; ^
`koa.use(async (ctx, next)=>{`
/ b, R% N" Q z. i5 m `ctx.body =` `"body可以返回数据,"``;`
1 c2 b" X | p, M! @ `ctx.body +=` `"可以多次调用,"``;`: B8 b* o% m+ y
`ctx.body +=` `"不需要end()"``;`- {" w9 O4 R, _; h% M7 _8 [2 y) f
`});`
% G' M) ?. r1 X2 t `koa.listen(3000, ()=>{`
- @) b9 Q2 m$ w+ P `console.log(``"监听开始"``);`
* Z' I7 b. {; O3 e a$ f5 |7 q' y% A& @( ] `});` ! K! U: a/ U# d
效果:
+ [+ Q- K7 F, n; [$ q$ o9 s0 Z / x( v$ j# i* L3 T3 V! d: O
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type 1 E# h. E: d1 c6 w+ M; Z
`const Koa = require(``"koa"``);`2 D: M: \$ X, m; @9 Q0 ^
`const koa =` `new` `Koa();`+ P L& R5 f+ t- m0 }- _
`koa.use(async (ctx, next)=>{`: K9 w( A9 W9 a( f9 A% j
`ctx.body = ctx.url;`8 H% [8 u4 _6 P. n; ^
`ctx.body = ctx.path;`
* t" _3 s1 C/ B) \* L) k `ctx.body = ctx.query;`
6 i* {- a; H/ \/ _2 a: B `ctx.body = ctx.querystring;`" k" Z3 {# g2 L# y: ~& S& t
`});`' b. A8 z p; C7 u
`koa.listen(3000, ()=>{`
8 N* X( c; b" e% \4 F: K+ R `console.log(``"监听开始"``);`
7 M" e# y1 C0 e' n! \6 J8 V! i `});`
/ V' X8 e. m1 V, h 访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
+ U' t+ a0 T/ {2 P* M 1. url: 整个路径
/ Z" i! ~) v5 d X' A$ }3 `9 ]$ X , x9 W' S% {+ e, h
2. path: 非查询部分 " `8 a6 e! H8 Z6 Z+ g
3 e3 h9 c& b2 D( h9 e
3. query: 将查询部分转为JSON对象
( w, j/ S) u1 S$ Z& s/ ~7 I) v
- |' j" [6 l% m5 o 4. querystring: 将查询部分转为字符串 3 B- O q& p6 ?0 ~4 D
@; \# e6 Y% K& F, @ 5. ctx.state ,ctx.type 表示状态吗和类型
; C( S; c, K' h" i, w# Z% A; w 2.简单爬虫练习
/ G: E$ v+ S3 X7 D- v. { 安装request,cheerio模块 8 A( y' u! a5 z0 @4 M3 a$ d! E0 d* v% B
`npm i -S request: 请求模块`
4 E, q8 X6 W0 V+ w `npm i -S cheerio: 抓取页面模块(JQ核心)` ' H8 F1 H: I: h7 K0 V8 z
抓取网页数据案例(随机网页) : t% r7 y8 _3 a$ a
`//导入模块`
4 ~, @+ G1 F$ [9 R1 I5 t `const request = require(``"superagent"``);` `//导入请求模块`
2 m* B& P' _* ?2 s7 i% C5 |. H& \ `const cheerio = require(``"cheerio"``);`
& g4 R4 c2 r, C `const {join} = require(``"path"``);`
1 B+ r3 Q) k3 Q1 s- X" m& o `const fs = require(``"fs"``);`
# e' f8 V" O0 [% O6 H% h/ \ `let arr = [],` `//存放数据`2 r6 n$ `. k# p! V7 Z$ ~) c
`reg = /\n|\s+/g,` `//replace中使用`- V& X9 T8 j# k4 ~
`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/)"``;`
5 z1 _' v3 j; T2 Y" J `request`
+ ~: k8 _; w% F3 |% K& A* I4 ? `.get(url)`
6 v: W$ A- U% y7 F: K* M# V `.end((err, res) => {`' a& N1 @) ]) G
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`$ \& ^& \3 T# q9 M4 C6 z9 W9 H
`$(``".course-item"``).each((i, v) => {`
) N/ R/ S; w& a7 l `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`) \$ l9 [' `2 A* G; o! l4 ?
`const obj = {`
+ _* n8 W6 c6 S, t2 }- r `imgSrc : $(v).find(``"img"``).prop(``"src"``),`* Y+ W7 a- o) T0 i4 l, X
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
i! Q2 _/ U. I/ Z `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`3 `; T# ?/ o3 G6 r" N" l& L- b
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`1 l7 c& `9 m- ?' Q# ~' d5 @
`};`
- {0 G1 x4 I0 N+ ]. Y `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`; w% E" M8 N1 d$ B$ V7 Z9 k
`arr.push(obj);` `//把对象放进数组里`! j' ?0 W. C+ q0 j/ z, C
`});` C1 k, i$ z* M( z. B0 S, A8 F
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`
. N; }% x5 j' F+ W6 o& _ `});`
' x* k: g2 {+ p+ x$ b5 K. B- U 以上就是本文的全部内容,希望对大家的学习有所帮助
/ p- U; A! v7 F. z$ ?% z- f. {2 U( O2 [' e( [
$ C1 j% z R p
6 [3 p/ C- B4 ~4 R H; {7 d
6 P+ E0 i- e& H$ [
|