|
& f+ D" G2 N, d. g V. G$ \) O
Koa -- 基于 Node.js 平台的下一代 web 开发框架
9 a7 [0 A0 e3 }, x8 \ koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
5 R! x) u5 ~9 F; B% L3 J) v2 X 英文官网:http://koajs.com
0 P, W+ J$ Z; u2 l" ?& ~ 中文官网:http://koajs.cn
2 I3 M8 S" L9 b' ^0 R' \ 1.koa + g& T% c4 Y, d% u
安装koa包: npm i -S koa@latest _* \' u/ S) T4 R0 c
引入: const koa = require("koa"); 实例化对象: const app = new koa;+ A! e- O4 P3 x. X+ q0 M- n# `; m
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册
3 J# \( q4 y/ M$ l% c) s8 S6 Y use()函数中必须使用异步 async; use可是调用无数次;
; @8 I9 O* L" E3 d0 ~2 \% P6 ?6 `1 s 其中有两个参数:
0 v( ~+ v" U+ |* d @1 D a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 - V: ?6 Y5 d7 V4 o4 h
b)next: next(),将本次控制权交给下一个中间件。
9 Z' U) S$ U2 w: f( F4 a! H 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
. S, @) g# t0 z1 h9 `, i: f9 o9 E 1. next参数的使用demo
$ y1 P: n1 G0 w `const Koa = require(``"koa"``);`7 o) | t& K1 {" C; J
`const koa =` `new` `Koa();`2 V4 y$ ~( p; l; T) r# C! c$ i% r8 l
`//中间件1`' v1 |2 u7 O) W3 X
`koa.use(async (ctx, next) => {`9 @; |9 \* R B/ m- e9 y
`console.log(``"1 , 接收请求控制权"``);`
& G* k- Y% h& L1 H: ^) E4 l. D0 e8 w `await next();` `//将控制权传给下一个中间件`
/ r$ l- H J) b `console.log(``"1 , 返回请求控制权"``);`
3 B" l1 ]9 K% [* V$ |$ G' d3 M `});` `//将中间件注册到koa的实例上`
- d; Z7 f, o9 ~ w `//中间件2`
) P. S g! e( Q) L& [! m# n4 V `koa.use(async (ctx, next) => {`) t5 }0 s1 c, h3 J2 ?) u1 }( r! b
`console.log(``"2 , 接收请求控制权"``);`6 G( C* _) M7 \3 R
await next();`5 n/ E9 R/ B& ]! [$ @2 k6 {
`console.log(``"2 , 返回请求控制权"``);`2 I) N& y& w5 y% B3 {* L% \; E5 q4 A
`});`. p+ r0 u9 V6 ?# ]5 Q- U
`//中间件3`
6 y+ i6 B4 H: V% H3 K4 w! K9 x1 V `koa.use(async (ctx, next) => {`" j* A, f8 d* O
`console.log(``"3 , 接收请求控制权"``);`$ o4 z& Y$ O' l
`console.log(``"3 ,返回请求控制权"``);`. p% J5 h* V4 `4 P# C
`});`3 F7 u/ ^& L- }
`koa.listen(3000, ()=>{`
p! C+ ]0 G, @$ ~$ K# z1 | `console.log(``"开始监听3000端口"``);`
- E2 g$ Z3 C- [9 F5 O l `});` - R0 w; {; H5 H5 w4 o6 P5 N
注:当中间件中没有next(),不会执行下面的中间件
5 Y9 f; _, Q' b, M 访问localhost:3000的效果图;
* y2 H% b: X$ E) M& C5 L. E 0 H t6 ^+ |. }* R8 U
注:会有两次操作是因为图标icon也会请求一次
: i) ]* c0 Q3 a% j, p0 M, e 2.ctx参数的使用demo ) Y& G9 L: o* Q+ _6 V! n
`const Koa = require(``"koa"``);`
; \- \$ t4 u$ z1 X5 |3 } `const koa =` `new` `Koa();`8 l) Y/ V4 ^8 y7 c1 L* @% d
`koa.use(async (ctx, next)=>{`
* l) @* b2 y/ ]' Z, p0 _ `ctx.body =` `"body可以返回数据,"``;`
4 N) q) M( n( r C. A/ F `ctx.body +=` `"可以多次调用,"``;`7 j1 e! p4 L) h Z! a
`ctx.body +=` `"不需要end()"``;`
5 _/ P, [. A0 I6 D3 _1 k8 [ `});`$ B B. w7 K! f o
`koa.listen(3000, ()=>{`/ l2 S8 g$ Z1 S$ M
`console.log(``"监听开始"``);`2 F7 q( p& m# G4 [+ L- G3 {
`});`
% e. X1 k+ e/ J3 n* J" z 效果: / n" w! O7 N% J. A0 R* u% a
( | [6 Y/ C1 d5 T# ]' U% J! u ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
& @8 ~0 |- y9 |# H F k( E6 k `const Koa = require(``"koa"``);`& N" B0 ]9 v- Y& ~" r: s& o4 A6 v
`const koa =` `new` `Koa();`9 l5 o( ~% F/ |6 y3 C! T
`koa.use(async (ctx, next)=>{`8 ]+ r0 Q: R: l( n" u
`ctx.body = ctx.url;`- i: l; Q* J( y8 t
`ctx.body = ctx.path;`
% d8 P3 W; O: p5 r* C `ctx.body = ctx.query;`% n) \/ r9 @2 h! V6 G2 w {
`ctx.body = ctx.querystring;`
+ y% ~& o7 E) N& b3 a7 l- b `});`
5 @( Q* Q6 U/ n% }9 ~3 l `koa.listen(3000, ()=>{`2 l$ T/ L2 I- G: ]3 A5 J+ s
`console.log(``"监听开始"``);`
5 l3 \" u% E4 e6 E4 v4 B l! [7 I `});` / U0 L0 P. I3 ]
访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
4 h, m3 r. {; `8 U+ P. G* ` 1. url: 整个路径
9 p4 \9 _* V- H& _ C
. c9 h+ S3 A" F# c7 ]0 @ 2. path: 非查询部分
1 e5 x0 _: u9 g* q4 ]2 k3 b9 C
4 d/ U6 ?3 d9 X% P7 J 3. query: 将查询部分转为JSON对象 . B. j& P( W- e5 h6 F6 b
3 R* G. I2 l' J5 l* K$ V 4. querystring: 将查询部分转为字符串
# `& V8 s5 a3 G
! u0 b! f( }( q, ~# Z 5. ctx.state ,ctx.type 表示状态吗和类型
$ U' t1 t ` d d 2.简单爬虫练习 , _- z# A* K2 J2 j6 v7 P d
安装request,cheerio模块 / A! r6 R" j9 x8 S
`npm i -S request: 请求模块`. H; q5 p4 ?, X: C, D+ l$ q
`npm i -S cheerio: 抓取页面模块(JQ核心)` 6 I5 n& D0 Y. ~* J
抓取网页数据案例(随机网页) - N8 E" o9 Z+ s* q' e7 Z
`//导入模块`" h# k+ b: a3 ` b6 E
`const request = require(``"superagent"``);` `//导入请求模块`
# K. ]' ^8 }0 X" d `const cheerio = require(``"cheerio"``);`
/ ?* J; q0 a# D/ x$ P, V0 ` `const {join} = require(``"path"``);`
3 p, \ w9 p* f" K0 {& `) q. | `const fs = require(``"fs"``);`
" H! t3 y. X/ E `let arr = [],` `//存放数据`8 t, Z; J a/ w# A5 w
`reg = /\n|\s+/g,` `//replace中使用`5 [# ^$ F$ T3 x. T2 Z$ 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/)"``;`+ M# V1 h* o. T w, ~( |$ s. L
`request`7 W4 F9 B8 l% w8 d9 l) E
`.get(url)`
' w% t/ e" N! Z+ X( i- s1 S( ?5 r `.end((err, res) => {`
( J: a' j1 f& `7 a; @1 b8 M `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
9 }+ \3 j; |; B* n `$(``".course-item"``).each((i, v) => {`
/ X! d5 X3 |$ ^5 w `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
# H( i! x) e4 N! E" R" [ `const obj = {`# }: Y, M: E5 P; d* x- A2 Z
`imgSrc : $(v).find(``"img"``).prop(``"src"``),`; y+ r/ M( G2 w
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
" Z7 m2 h+ O2 b! J) P5 j0 ^ `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`- Z' U+ c4 H* z
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`, Q: C- p+ ~1 v" H* |2 l! r
`};`$ {! u7 w5 q% L l" ^" {1 b
`console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
/ }/ v+ x( P! u$ M `arr.push(obj);` `//把对象放进数组里` O$ B4 A& N; Q9 I
`});`
8 @) x1 G0 D% p% W# r# B `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`
* S- p# L7 k ~8 g: z' S1 \ `});`
/ d; t& ]0 J$ ^& y 以上就是本文的全部内容,希望对大家的学习有所帮助
: e& s' Q4 _$ U) T) e
1 K% H# n9 c5 U
4 B6 Q. f% y. r9 L8 F. `1 V% l0 | v; I" _. i7 C2 L9 y
1 q/ f' f5 M3 l4 ?$ A# J
|