|
1 [( `( K" V S: K Koa -- 基于 Node.js 平台的下一代 web 开发框架 0 m. a. Z: |4 X) ~( ]
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 ; P+ c. O8 a: q. e/ {3 A
英文官网:http://koajs.com
) {% Y- J: o2 z+ C& R: H1 v 中文官网:http://koajs.cn
, h( F' I1 o# V/ m, I 1.koa 4 O# y+ i8 ]/ v: z6 Z0 A# Z
安装koa包: npm i -S koa@latest 9 k% O D8 i) x6 n0 s
引入: const koa = require("koa"); 实例化对象: const app = new koa;0 O+ r C: e$ H. \2 Q
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 " E; J9 k! w( e1 m" E
use()函数中必须使用异步 async; use可是调用无数次;
- A4 Y! v9 G; Q/ X/ V3 q 其中有两个参数: ) e1 s M2 q2 G
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 / M$ t* e" P- j4 c6 S% {- H; o
b)next: next(),将本次控制权交给下一个中间件。 6 \) U) c, U+ M! }3 h' g+ J. @( |% t
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 $ [' y: i7 l8 n1 F9 o
1. next参数的使用demo
+ W+ b u" A. P$ a4 }$ Y `const Koa = require(``"koa"``);`
8 x" K4 P6 C$ e6 F `const koa =` `new` `Koa();`7 |/ f% E$ g: ]3 u z* ^5 L
`//中间件1`. W9 N3 I, [1 J& {8 P/ W% u, h
`koa.use(async (ctx, next) => {`
) U) m. ^) b/ b% O `console.log(``"1 , 接收请求控制权"``);`3 X9 A& D; }. Q' ^. T
`await next();` `//将控制权传给下一个中间件` ~3 ~ w& V. B% U, Q
`console.log(``"1 , 返回请求控制权"``);`5 [' K9 q6 F' @! }; c" l1 R- x
`});` `//将中间件注册到koa的实例上`
/ q' @5 A# @" x0 P$ c4 ^ `//中间件2`
. }/ _& d, L1 v `koa.use(async (ctx, next) => {`8 R; F b: F' i. G+ N
`console.log(``"2 , 接收请求控制权"``);`4 }4 b3 T4 V1 s6 |# W) @$ [
await next();`
/ I2 x0 X, [& \1 d, n" B! }2 ` `console.log(``"2 , 返回请求控制权"``);`
4 D* Z$ X% z+ n9 v+ P) c+ g `});`
3 @1 F j. v% M2 P3 P; }7 B `//中间件3`
, y$ D. O7 l# p `koa.use(async (ctx, next) => {`
1 @1 \% e3 _2 }2 S+ E; ? `console.log(``"3 , 接收请求控制权"``);`
. y5 G! y& c& F6 i `console.log(``"3 ,返回请求控制权"``);`
! P; ` ]8 X: ?. z4 U. Z- @. T `});`
8 r* h4 W; P/ f# x6 T9 Z `koa.listen(3000, ()=>{`& ^# M" q u/ M6 p' f& Z6 M
`console.log(``"开始监听3000端口"``);`9 q. V3 C8 z( r# t1 r
`});` L( z7 C2 }3 H+ Z0 ^+ {0 v
注:当中间件中没有next(),不会执行下面的中间件 6 A% C$ w9 @+ J( k$ a6 F2 Y
访问localhost:3000的效果图;
% a% X5 [+ I; p' R. V
$ H. @) B5 \/ @9 \ 注:会有两次操作是因为图标icon也会请求一次
3 _' N, o/ V5 y 2.ctx参数的使用demo
* l2 N, G+ S' s- t7 v* k! u `const Koa = require(``"koa"``);`3 g2 C1 d O, Q q- X7 x2 b
`const koa =` `new` `Koa();`
, }6 v- g3 b$ |' x+ f3 \ `koa.use(async (ctx, next)=>{`
. g! y4 Z9 C: G& s' w/ u `ctx.body =` `"body可以返回数据,"``;`
& r2 t$ j' o* Q; d+ X5 t `ctx.body +=` `"可以多次调用,"``;`
, T3 r. `8 V9 ?; v; h8 x `ctx.body +=` `"不需要end()"``;`+ C( q( @0 Z. M" `3 R
`});`
, r# S) q G( s( r9 f `koa.listen(3000, ()=>{`
$ S9 L+ Y9 v* U* w7 Y( ? `console.log(``"监听开始"``);`( g( g$ Z9 e$ Y' V
`});`
; K8 O! X4 j) n( b2 W7 U) k 效果: , z1 N' Q( v: g8 H; }/ y8 T
' a- m8 ]5 d- T) l" z4 L
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type ! G9 G) [( N2 k
`const Koa = require(``"koa"``);`9 J' Q" O" w4 F0 V3 A! a( D
`const koa =` `new` `Koa();`
& D5 D+ P: L3 P! I/ V7 R" d `koa.use(async (ctx, next)=>{`
( m V" |( h& ^- h8 n K- b9 w* `; ^ `ctx.body = ctx.url;`$ f8 m! S* j$ _% j1 m
`ctx.body = ctx.path;`
( z) r" k& U4 b# J' ^2 r( e `ctx.body = ctx.query;`6 e; \3 `. j# Z, x
`ctx.body = ctx.querystring;`( l9 b& y2 D5 J1 ]" V* @
`});`
/ t2 T; D6 P# b* Y/ y* \9 p5 A `koa.listen(3000, ()=>{`
( e- \# R! s& L( Z/ j$ C `console.log(``"监听开始"``);`
. G6 }) y2 N3 V. P; ~ `});` 3 A- F6 z8 N, b( O& C
访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
. q$ m' X) Z4 T; `2 W 1. url: 整个路径
$ f; w. |' x. ?8 ^1 z8 Z1 W % I& O: q6 K, |
2. path: 非查询部分 5 f2 g! J2 s: ?6 A! I
9 K. w# K ~8 z0 ^& Y 3. query: 将查询部分转为JSON对象 8 e; O+ `9 V3 A! j9 b
( Q8 D! p8 o3 u; o. `8 N
4. querystring: 将查询部分转为字符串 / E- g& t3 t& [" v o4 j
5 y3 f" D# o9 f4 e/ f
5. ctx.state ,ctx.type 表示状态吗和类型
: i; h/ t3 ~$ V* \ 2.简单爬虫练习 # V3 N0 Q/ K/ v0 }9 T, W( p* r
安装request,cheerio模块 # a% `* a3 }2 ]: \7 z
`npm i -S request: 请求模块`
$ l' }/ s; }! l2 N4 @ `npm i -S cheerio: 抓取页面模块(JQ核心)`
2 \ ]) y; K0 e9 R; s 抓取网页数据案例(随机网页) + |$ l" A3 A: X( x8 _/ R g
`//导入模块`( t6 P6 m. K4 _2 x. ?
`const request = require(``"superagent"``);` `//导入请求模块`
$ b6 E2 x, s- y0 P; v `const cheerio = require(``"cheerio"``);`7 _% U7 |$ v! `. _
`const {join} = require(``"path"``);`0 {& \4 C) l7 ?( ]9 ~5 N+ v
`const fs = require(``"fs"``);`( O' u' i+ n8 F
`let arr = [],` `//存放数据`
9 t7 M8 i4 D( l: e `reg = /\n|\s+/g,` `//replace中使用`
4 U' y8 x! H/ U* E) h! w$ R3 e `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/)"``;`
2 M! O: Q" E5 Y; M. k" f4 v- D `request`7 v2 ]+ g# G$ G6 O% I( _; S$ s0 ~
`.get(url)`
0 M9 u( p: ^3 ]# g/ P% D `.end((err, res) => {`
1 H4 `* v. _/ g! |% ^4 B: Z `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`$ J+ u) Q6 Q9 _% S5 o" H' r6 b3 X1 `
`$(``".course-item"``).each((i, v) => {`
e" U9 D$ g5 W* d8 C+ B `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
+ d7 f& P1 R# G9 @ `const obj = {`
f4 ]9 p+ z$ P; p) ~ `imgSrc : $(v).find(``"img"``).prop(``"src"``),`
" V7 w) N) N1 z `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
9 F ?" X8 n6 n- B$ j5 M7 ^ `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
! d* x7 D) j& X: y* ^- |2 x/ \ `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
+ E. g# z+ ~# {- f5 ^ ?% e `};`
* T# u7 j: v1 {+ e8 q0 g3 a `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` u2 q- U5 t8 h3 b9 S5 q
`arr.push(obj);` `//把对象放进数组里`0 S# W$ g/ L5 k1 b# F( X g
`});`
- m o7 {' x4 h+ f `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`
: k$ f' n6 K1 a3 O `});`
8 j; P, s) o! e+ f/ i 以上就是本文的全部内容,希望对大家的学习有所帮助 5 ^; ]# z; V: a& g
7 W7 Y" ]: Q: X$ R
6 b! z+ c) M; T+ t1 b* s0 G
% g/ ^: F( H, @9 K1 f
5 N/ q1 P3 C6 i1 a# z9 h. I* Y0 V2 z |