|
% l7 F+ r! ]3 q0 X* B4 E
Koa -- 基于 Node.js 平台的下一代 web 开发框架
, @5 h0 y6 E% L+ k koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 4 [$ W% v* W1 ~ ~( c6 g
英文官网:http://koajs.com
/ D9 q- H N) C1 c, a. h 中文官网:http://koajs.cn " _# Z/ r- B; b# s2 F1 G) s
1.koa
- m' Z5 b8 }1 Z* l 安装koa包: npm i -S koa@latest
/ f$ i) f2 {; X; w8 g 引入: const koa = require("koa"); 实例化对象: const app = new koa;
! F4 `9 m5 `* E 通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 4 h3 c, M- K: T, c
use()函数中必须使用异步 async; use可是调用无数次;
7 Z4 |3 t" F& Q' X6 S 其中有两个参数: + q1 u: k1 W1 t0 g
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 - ^4 C, f G9 o# D1 d; d& l
b)next: next(),将本次控制权交给下一个中间件。 $ t7 y! g9 }/ Q
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
9 ]! x2 v% U$ v3 M. d 1. next参数的使用demo 9 l) ?# E* \8 d% Q3 ~; o
`const Koa = require(``"koa"``);`
$ W. N, W! _1 C7 F+ }+ ? `const koa =` `new` `Koa();`$ K9 |" C" d$ ~+ J4 n
`//中间件1`
/ ^. N$ {% f( k9 b5 i `koa.use(async (ctx, next) => {`
& E l u P# C( z/ ~ `console.log(``"1 , 接收请求控制权"``);`
# u2 s; [$ }7 l2 k `await next();` `//将控制权传给下一个中间件`9 k/ H" L1 P5 ^# S, D& J" Q
`console.log(``"1 , 返回请求控制权"``);`
3 o! u: C! W ^* r0 k `});` `//将中间件注册到koa的实例上`
/ q: s/ }/ d% W7 v2 I+ N1 u `//中间件2`3 W- m/ r/ d Z u. ^) v3 v) _
`koa.use(async (ctx, next) => {`
4 Z, {$ J! W7 w. e& R `console.log(``"2 , 接收请求控制权"``);`
& V! v6 X% J# G5 V await next();`
, A- x2 f4 w+ K( R& K6 X `console.log(``"2 , 返回请求控制权"``);`
& `/ b) l- Z g `});`, B# _; G2 {: g3 V
`//中间件3`
/ p( }8 E7 | V `koa.use(async (ctx, next) => {`
0 `- ?# c* h8 } `console.log(``"3 , 接收请求控制权"``);`" D% S1 ~1 E9 c# {0 ?& g' O; D
`console.log(``"3 ,返回请求控制权"``);`' r% e' m# w) ~3 i- w
`});`
( T5 B0 W: }" \2 U) N; D3 I- | `koa.listen(3000, ()=>{`- b8 C; r' x0 A& f9 ]1 k
`console.log(``"开始监听3000端口"``);`
' H- t* W6 n* X( X6 \9 \ `});` 8 b, {# U/ d" v' h$ l
注:当中间件中没有next(),不会执行下面的中间件
. y/ s7 g7 T, B1 z0 _: j 访问localhost:3000的效果图; 7 c- j9 L6 o9 @# a9 g+ F
0 e3 z9 Y6 E6 z X
注:会有两次操作是因为图标icon也会请求一次 ' O! V: V2 C3 J. m) |1 |
2.ctx参数的使用demo ' B9 m% m2 {2 w8 m' x, O: k. \" T! w
`const Koa = require(``"koa"``);`6 x8 K, n& B* S8 B# ?1 x0 z
`const koa =` `new` `Koa();`) j: Q5 u! c6 B' Y+ {6 t r
`koa.use(async (ctx, next)=>{` U+ L& s# e9 \; B" T$ a
`ctx.body =` `"body可以返回数据,"``;`/ q# {% A' B/ v1 A" c: j% J1 ]& `9 }
`ctx.body +=` `"可以多次调用,"``;`
6 x$ z$ a% y1 F: _ `ctx.body +=` `"不需要end()"``;`, Y5 D+ U% ]+ o: P3 ^# _
`});`
" g( |. i% w [1 t `koa.listen(3000, ()=>{`$ |. {+ L6 P. y: Q e! p3 D
`console.log(``"监听开始"``);`
' C& H; Q; m. M4 U `});` M" A% B9 L" T8 c- g! C! P
效果: 3 O6 E7 g& i% G8 p
- U& D+ F5 C8 R# u/ k6 R ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type 5 _9 x9 G; E2 J, q* x9 s! B% L
`const Koa = require(``"koa"``);`! @0 j# a: a# Z h9 C
`const koa =` `new` `Koa();`
3 ^( U3 b- e# L" a1 c `koa.use(async (ctx, next)=>{`
+ S8 u) d/ |* b8 S9 n# I `ctx.body = ctx.url;`) K- j4 D/ j2 Q2 w
`ctx.body = ctx.path;`9 f/ h3 x w+ N2 k* j y9 ^
`ctx.body = ctx.query;`
" z l7 h4 E# L6 A `ctx.body = ctx.querystring;`
# a7 X1 B% m5 i" F6 w# _! p `});`
# Z7 v, c5 J& R `koa.listen(3000, ()=>{`
* a' ?+ Q$ ^+ b& `- N4 H `console.log(``"监听开始"``);`
4 Y0 q: A, M) n. E) @0 @2 n, Z `});` 4 m; \! ]: a# [3 I
访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
^4 X( T2 S$ [+ {% p" ^6 L 1. url: 整个路径
+ c: @( v7 p0 ]& b e: C0 c. T0 Y) G( s 4 e- I% I4 f- q1 I( B
2. path: 非查询部分
- |. Z% U) |$ t: k5 z) [
( U- E8 j" u* f 3. query: 将查询部分转为JSON对象 * }! Q! d6 I1 [6 ^
0 Z/ T9 S8 R* L
4. querystring: 将查询部分转为字符串 # l, Q2 O+ R* r$ i3 Y
2 j+ B, k6 J( ~( X- R4 N" G
5. ctx.state ,ctx.type 表示状态吗和类型 8 ^$ p1 n/ c1 M j* c
2.简单爬虫练习
8 V9 Y V% i) j) z2 { w5 p 安装request,cheerio模块 4 k, K5 n# L0 w1 I; ?0 m( N( L/ g% r
`npm i -S request: 请求模块`
5 I0 G& F3 ]7 y0 e. h+ T- W `npm i -S cheerio: 抓取页面模块(JQ核心)`
( U" a9 z. C! [ H/ r# |1 ^ 抓取网页数据案例(随机网页)
7 }/ o5 W$ K \0 U3 K5 _2 U$ L `//导入模块`
8 r1 H& P8 G$ @/ h8 e `const request = require(``"superagent"``);` `//导入请求模块`
' a! f8 Z9 Y" T f9 [" p0 E% @ `const cheerio = require(``"cheerio"``);`, c1 S1 M) V! z
`const {join} = require(``"path"``);`2 b4 V; O! Z/ `7 i, u! L
`const fs = require(``"fs"``);` b8 l+ B0 ]5 f) l$ ?5 I
`let arr = [],` `//存放数据`
, x9 i' B3 g# J1 i `reg = /\n|\s+/g,` `//replace中使用`
# ~% ?, \; p+ C0 A, |7 M `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/)"``;`
6 ?1 ]0 f& [( K0 d `request`1 b4 j* B0 Y9 C6 Y' z
`.get(url)`3 W0 E4 V# l5 g w8 P
`.end((err, res) => {`
0 Y8 x* L0 d4 H `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`5 h: _# R) h; C% I
`$(``".course-item"``).each((i, v) => {`9 C8 B; }' W8 Z# G- S$ E8 M
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
# V( G& }" W0 w+ O* y2 j `const obj = {`& n) S# I0 T) r: _. y
`imgSrc : $(v).find(``"img"``).prop(``"src"``),`
# A. |/ C3 d1 [( S$ ?' ^/ n `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
$ ^7 C$ o" J+ k2 a! ]5 Z( s9 K) ] `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
% R- T- z, S4 y+ j4 ] k `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`# t9 e* [, h. l
`};`
3 u- [/ v$ P W" ]1 [8 ~ `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`" F# p6 |* T: ^- x7 L% ?
`arr.push(obj);` `//把对象放进数组里`
4 f) g% x/ r( H7 ]& @ @ `});`% E1 M" ^1 P! i$ T( y S& T
`fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`
# T' _. P: B- ]; d6 ]% v6 H& L `});`
& f3 _: o* P) b: C% K1 Z 以上就是本文的全部内容,希望对大家的学习有所帮助
8 I6 {. R4 P7 S- n2 h
, s( o: n) Z2 l6 w" L4 S
6 b2 q. c8 i- n/ f
1 |' o* x& ~8 L
2 ~: p, \: b0 P/ c( }2 P" e7 K |