|
3 j% z1 X: I6 _" j
Koa -- 基于 Node.js 平台的下一代 web 开发框架
' `: A4 y" A; ?, U$ \6 I koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 ! c3 O# Q. n& Z( ?3 F: [- E
英文官网:http://koajs.com 1 [7 E b/ x. A! f, d- t" t4 v
中文官网:http://koajs.cn + i. \! u4 i2 v* l! I! ?
1.koa " l! C6 C, r& k% J) e7 ]. P$ ^
安装koa包: npm i -S koa@latest
: \9 R+ o7 _0 ^9 H. m( b+ a 引入: const koa = require("koa"); 实例化对象: const app = new koa;; ?" @% Z( u/ t
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 , z3 [: f4 `! U. s$ e; G% E
use()函数中必须使用异步 async; use可是调用无数次;
T, ^# T: `$ z, z1 n5 Y; t0 Y 其中有两个参数:
& P- ], ]5 q8 T& L" c% K% A) Q a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
1 H$ a8 Z1 q4 X1 N* E+ k3 \2 J6 ? b)next: next(),将本次控制权交给下一个中间件。
3 L# S, v$ x' _/ ~6 z 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 * B" g+ i1 ~2 M, [7 _* t5 v
1. next参数的使用demo
- r8 G0 ^4 c9 \4 q1 u! ~ `const Koa = require(``"koa"``);`
+ b' y' f8 t3 Y- c0 M) J `const koa =` `new` `Koa();`, ^. J8 p( k. B- R/ @% q
`//中间件1`
# M( i) e% B7 b8 i `koa.use(async (ctx, next) => {`
5 v: U% u5 y6 D* h. k# b* z `console.log(``"1 , 接收请求控制权"``);`& x3 Z- p9 e, b( ~, L
`await next();` `//将控制权传给下一个中间件`
' D+ V! }, I0 L& g% H) X1 l+ | `console.log(``"1 , 返回请求控制权"``);`6 ~6 Z& R4 L/ K7 L1 a7 u o
`});` `//将中间件注册到koa的实例上`
1 z& u/ y1 l2 H. x2 }! B3 u `//中间件2`1 {, F6 {" Y2 g/ @
`koa.use(async (ctx, next) => {`
& \# S, k+ A; t. v `console.log(``"2 , 接收请求控制权"``);`
2 W3 @ j" r5 ]6 N await next();`! a; z/ b; @" B, [" C! U3 d
`console.log(``"2 , 返回请求控制权"``);`
1 B% d) {* \) s, e6 x' \$ ^6 w `});`/ K5 i. }% M; S5 e- L2 x* S
`//中间件3`
. G9 s4 }! e( y: ]# \ `koa.use(async (ctx, next) => {`
5 t; j+ p; l' J8 w# E+ b. G `console.log(``"3 , 接收请求控制权"``);`: @% `0 J E( ^7 N
`console.log(``"3 ,返回请求控制权"``);`, H6 W1 B' W/ ?) Z. A, \
`});`
$ y4 p, `3 B& F `koa.listen(3000, ()=>{`
/ b1 `1 T4 |& f' P4 N6 x6 ~ `console.log(``"开始监听3000端口"``);`' J( g- r- Z9 x+ N
`});`
: \2 i6 _6 U* t; \& t 注:当中间件中没有next(),不会执行下面的中间件 7 ~* ?8 x! [6 i7 v, a" B7 L9 Y( C: z
访问localhost:3000的效果图; / g" |. g0 B$ K) C
. x ?( B" |6 S5 ]4 B 注:会有两次操作是因为图标icon也会请求一次
* ~2 I1 S6 @" N2 F 2.ctx参数的使用demo 0 Q- C' j- }& `% g, @" j: e
`const Koa = require(``"koa"``);`
& V. E( L& V0 {5 L F7 b6 ]7 \ `const koa =` `new` `Koa();`
* n, m6 i K% F u! G, z `koa.use(async (ctx, next)=>{`
! X, s2 k2 [* j" D `ctx.body =` `"body可以返回数据,"``;`
& e' q2 V% q4 a- n; ^$ ] `ctx.body +=` `"可以多次调用,"``;`
! M. |9 Z% s5 h `ctx.body +=` `"不需要end()"``;`3 p: ?6 Z+ k$ p4 f m: _. V4 A7 x
`});`
4 r- @8 z6 g1 \" S m0 w `koa.listen(3000, ()=>{`9 |4 [, I4 r/ T9 c8 ~
`console.log(``"监听开始"``);`
+ B7 K1 U) N' A: i" H `});`
0 {0 g: R4 Z! s: o8 j 效果: 1 ?# v- p1 H. Z" R# R h! ?( D- D% n
* \+ Q- H& Y4 d0 |3 F ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
0 \9 ~: N5 T$ V l `const Koa = require(``"koa"``);`/ S \* d$ Z: O" G' P/ y" V6 G) p% L
`const koa =` `new` `Koa();`
. p8 ?7 ?; u4 f4 H/ [ `koa.use(async (ctx, next)=>{`
) R: a4 e4 G0 S S3 q8 i& P# H `ctx.body = ctx.url;`
" W$ [1 ?2 c- A: I- l2 G `ctx.body = ctx.path;`' m3 W: {* i( K6 I' X2 f8 i8 ~
`ctx.body = ctx.query;`: l1 t& I* a3 q# {7 c4 x3 c
`ctx.body = ctx.querystring;`
0 z/ |5 @$ K6 ?8 d* n `});`- d% m7 o( f2 A i+ k4 E* Y% e
`koa.listen(3000, ()=>{`) d* A, c9 q) L
`console.log(``"监听开始"``);`
4 c# o. J& B4 G! n. ^ `});` + b7 U& S4 J; T ]
访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
9 B& q! }% o6 E* [6 B 1. url: 整个路径
* H, w/ F6 q# K7 g$ o& f# |9 G 1 @( o% Y& D7 V0 j
2. path: 非查询部分 4 i/ r% t- @0 h0 p% w" c7 y
7 h$ w+ `: e. K# Z6 I7 V- ?' v, L
3. query: 将查询部分转为JSON对象 * k+ o1 L- Y1 V2 D1 o
: |- z4 M$ W. x& h, m; S# r7 _
4. querystring: 将查询部分转为字符串
- m) I* D3 f( ^+ q8 o; A 6 U8 {0 q S4 |% b J+ k1 A% |
5. ctx.state ,ctx.type 表示状态吗和类型 7 ]) C/ k4 \( A
2.简单爬虫练习
" q$ L1 O3 t. h+ o" \ 安装request,cheerio模块
) Q2 N# d9 R% x' e3 [ `npm i -S request: 请求模块`' X( [+ n0 S' y6 X+ d* p
`npm i -S cheerio: 抓取页面模块(JQ核心)`
D4 o4 V5 i F+ y* T 抓取网页数据案例(随机网页)
7 L$ c! ?! q, Z( p) x" E' Z9 M- ? `//导入模块`; R7 j5 x" e8 U8 x
`const request = require(``"superagent"``);` `//导入请求模块`
6 f# u0 ^ Y6 u$ K `const cheerio = require(``"cheerio"``);`4 ^* ?) J. H5 f) M+ s
`const {join} = require(``"path"``);`" c% X+ ?1 `- w4 C
`const fs = require(``"fs"``);`+ ^$ S, E% I) b$ C1 ~; }/ h5 k1 P
`let arr = [],` `//存放数据`% E4 N/ {3 g& |- S0 _9 K
`reg = /\n|\s+/g,` `//replace中使用`% _# W% g# k) m; ~& |6 l6 j5 }
`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/)"``;` X) a# Z, x) T5 c: j2 u
`request`
* Y; m# l3 V- R1 ? |, w `.get(url)`
& J- z* Q& `( X8 P) m2 Y) e `.end((err, res) => {`( p% O" ^9 P: o# A- I
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
% G* Z" T" H+ g- t6 N `$(``".course-item"``).each((i, v) => {`8 S, D4 ?8 |6 ^3 N' z% k) B6 j. }
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`# y8 Z2 e) b" C2 w5 D$ z
`const obj = {`# q1 k) Z& e( ~. f, X+ v
`imgSrc : $(v).find(``"img"``).prop(``"src"``),` b6 g, {: ?1 U8 }' b; _
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`8 A" Y1 _- m9 h+ R( E
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
5 F0 f" q2 X4 ^: I# w* r `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
# e: [8 T9 I" J- k6 G `};`
) V& `% x1 p, k" z8 }/ x% i- O @ `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`
+ J- T. V9 T3 L: b4 D `arr.push(obj);` `//把对象放进数组里`
+ n4 \6 K/ f+ R+ | `});`( C1 E" e: X! @$ ~3 O' n6 P: o" p4 q
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`5 E, G- _* e7 z3 v/ q. a" d% `
`});` ' O; X7 @8 h N. v; g, i; p* S4 d2 V
以上就是本文的全部内容,希望对大家的学习有所帮助
" M; Y) \/ R( w, I" O
; L: S, M5 ^, W$ h' r8 Y p" q1 i2 p+ ]
5 \0 W3 _ T( R* q
& F, c! D5 ^% r! G9 N- f
# l1 M6 [4 m/ i# f5 X" ? |