|
' l9 e X* ?2 b3 t, Z; C3 a. c
Koa -- 基于 Node.js 平台的下一代 web 开发框架
; E& q- s5 }8 B6 b: O) b koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
/ I9 H! e- ? f% H/ Q7 `9 l7 u 英文官网:http://koajs.com
2 u4 j0 i. f& I 中文官网:http://koajs.cn
8 x- u. a* P4 r: W- X 1.koa ( a) E* `1 Z8 O6 j* d4 b k4 F& W
安装koa包: npm i -S koa@latest
4 X/ ~- h! w" J 引入: const koa = require("koa"); 实例化对象: const app = new koa;4 g2 Q. o% ?9 ~' m5 g: Z
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 : T' ~! R2 R& a) T0 {# @
use()函数中必须使用异步 async; use可是调用无数次; ' V& J5 X" U* p0 }
其中有两个参数: ' ^5 F) G; T3 {, H
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 z3 e( T3 q( ?2 U4 R. J
b)next: next(),将本次控制权交给下一个中间件。 7 e S; W; P3 J" M; h/ w
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 & W9 R2 R1 m' D' I- M1 _
1. next参数的使用demo
8 ]% _. P5 ~0 y `const Koa = require(``"koa"``);`
4 i) O6 S+ u' H `const koa =` `new` `Koa();`2 P' F2 N1 @( e% g0 f9 n+ I
`//中间件1`) u) P4 j! x8 a8 h/ d% G! L f
`koa.use(async (ctx, next) => {`
; u, V z1 I* k `console.log(``"1 , 接收请求控制权"``);`8 H4 P2 w, p3 B0 L' A* G
`await next();` `//将控制权传给下一个中间件`4 V5 E- ?# n$ e
`console.log(``"1 , 返回请求控制权"``);`7 S; h( s. I& ^/ A n
`});` `//将中间件注册到koa的实例上`* l7 e* J2 `1 v9 M# i- h9 @$ S
`//中间件2`5 d7 i' o! u$ L4 \
`koa.use(async (ctx, next) => {`- J* F% H/ ?/ Y# b, L
`console.log(``"2 , 接收请求控制权"``);`. Z" h4 }$ l l8 i
await next();`* G- f5 s( u P% z' T& Q
`console.log(``"2 , 返回请求控制权"``);`
5 D4 C# d x, r9 N6 M3 h; a. P `});`
A5 ?% a; ]3 D" c' g2 N `//中间件3`+ `4 y' s! M2 c# P, i r
`koa.use(async (ctx, next) => {`* F+ W8 n" t5 F/ F" v% s, W! |" Q
`console.log(``"3 , 接收请求控制权"``);`
4 m, s; \: t/ b# T, T' G `console.log(``"3 ,返回请求控制权"``);` z/ F1 R: ^7 b) [
`});`4 }) r1 w" N5 p4 Y8 r' n1 u
`koa.listen(3000, ()=>{`) s1 ^7 W9 P. c1 f' y
`console.log(``"开始监听3000端口"``);`
8 I& Z7 Q5 Q+ o! S' U* F `});`
/ Y4 J0 Q- Q: g, z! y# G 注:当中间件中没有next(),不会执行下面的中间件
; k$ G3 h B' M4 a- L4 j 访问localhost:3000的效果图; ; L i: z2 S0 ?% g7 t9 D4 j
: W6 E% A& s. f1 t' } 注:会有两次操作是因为图标icon也会请求一次
7 @" D* m W+ Q5 r) h+ k% v 2.ctx参数的使用demo
( t$ w& Y e+ I3 y, l3 G+ z `const Koa = require(``"koa"``);`; x" R0 ^' J0 _8 x
`const koa =` `new` `Koa();`
2 \; K5 g6 Q, k+ P; i5 P9 B5 S `koa.use(async (ctx, next)=>{`2 y0 h! f- Z& O
`ctx.body =` `"body可以返回数据,"``;`
% U5 A6 P5 U" W `ctx.body +=` `"可以多次调用,"``;`' X. P0 P/ o+ F6 O& ^9 }- T
`ctx.body +=` `"不需要end()"``;`
1 A1 U2 X! z" k" B4 B6 @ `});`7 Y' X8 ^" f' ?
`koa.listen(3000, ()=>{`
7 P. ^2 V* A, ?, ?$ u# S+ B `console.log(``"监听开始"``);`3 e! z; @1 i' z7 j$ s5 X% L9 u
`});` , s z7 ?) t; z3 G- n- \
效果: & d" y, r5 J" V' |3 g2 t* n: j3 O+ ]
N0 i. |# _6 _/ Z$ g6 F/ a: N
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type % I1 u, }. ~( {/ E- c! s
`const Koa = require(``"koa"``);`
3 ?/ d# O4 c1 X! R( I, Q0 F+ R# ]6 m `const koa =` `new` `Koa();`: E& S! s* C! K- I4 w2 [: k/ Y- O8 I M
`koa.use(async (ctx, next)=>{`
9 U! X0 n- }% z! M0 P1 a3 @6 R `ctx.body = ctx.url;`. Z% r# u, t: [9 O
`ctx.body = ctx.path;`
7 E1 k P5 D D8 p1 B7 c2 f `ctx.body = ctx.query;`% t" r+ K3 E. n$ b
`ctx.body = ctx.querystring;`5 R$ {1 \# e( ^
`});`
4 F o/ c/ k" H, F `koa.listen(3000, ()=>{`# b( ?3 J1 L: |
`console.log(``"监听开始"``);`. \ L6 U2 A1 k: W5 M0 m
`});`
& f% Z( f3 y6 N8 H, F, c; v. k; O 访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
/ g! M- z0 E. i# p 1. url: 整个路径
& Y: ]$ `& B6 n$ L3 B" f
4 r/ a+ F* ?3 a8 l e 2. path: 非查询部分
9 M# x- I4 K9 q& k# X
( B N3 m0 y1 B, | 3. query: 将查询部分转为JSON对象 2 B5 E& a$ B9 U0 y7 Q4 i) @
8 k6 R) Y3 ?4 G& T4 { 4. querystring: 将查询部分转为字符串 $ h" f3 x2 T$ D( X# o: V
8 l9 m! G6 F6 ?# x
5. ctx.state ,ctx.type 表示状态吗和类型 4 U4 |' y; Y. I& i# P
2.简单爬虫练习 6 d, A# z/ k3 y3 O. C# R& e% l( l
安装request,cheerio模块
: V% R! V0 o% a* R( { `npm i -S request: 请求模块`
U; y9 ^7 N) T6 a& V1 }" u/ p S `npm i -S cheerio: 抓取页面模块(JQ核心)` " _% k* X0 e, s) C3 \' f# D# f
抓取网页数据案例(随机网页)
% A& q+ V4 j; T* x4 A3 a `//导入模块`+ B( J# z) f1 a) W. t
`const request = require(``"superagent"``);` `//导入请求模块`
' r( f6 o( \& |. U& ~' j4 A `const cheerio = require(``"cheerio"``);`7 G# O- ]( \$ u
`const {join} = require(``"path"``);`
3 o. k1 ]1 p8 B4 `9 H" ~* O0 n6 x `const fs = require(``"fs"``);`# b1 f5 b/ p6 M; Z% y* @8 J
`let arr = [],` `//存放数据`( R3 c, ^, y( {0 V
`reg = /\n|\s+/g,` `//replace中使用`; ?8 C& H+ t y) N) u! Z) k
`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/)"``;`
& O" [* g4 B* d; n9 P/ [1 B `request`
# `9 w- f$ d: C9 o+ I `.get(url)`% F. D6 t* i/ Y+ l" ^/ p
`.end((err, res) => {`
T# P. s/ K) r; t2 ? `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`: x9 F0 B, K9 Z& L) A2 `
`$(``".course-item"``).each((i, v) => {`9 Z% u {2 d- I0 O) d1 W$ D
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
& T% f4 ?) f& V `const obj = {`& x, `; d) o+ c9 o
`imgSrc : $(v).find(``"img"``).prop(``"src"``),`
! `7 F, ?: a! f1 t0 ?3 ^ `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`$ t# b; H1 r G; H0 M" b
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
' n4 d8 ~, v* u `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`/ }' a( W. d% R5 ]. x
`};`. ]3 J4 o0 |5 i& D, A
`console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
6 X% e$ U* A% r: Y& p, y `arr.push(obj);` `//把对象放进数组里`
7 S; Z+ y, i' d `});`7 \3 x- }8 ^/ v2 e
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`) V3 i2 ~9 O) l
`});` ' i) b" v- y+ _" M( K
以上就是本文的全部内容,希望对大家的学习有所帮助
$ Z( D0 Q- o! A$ Z
" R/ _; L5 W, `& G0 t: @# `% u- G3 f3 \1 I& u: W
" L5 [0 ?* l" e! H5 z& {/ R$ i# S. B. ^( s1 `
|