|
# J, b8 T4 r3 C: T4 S
Koa -- 基于 Node.js 平台的下一代 web 开发框架 4 L2 H2 y+ {9 U+ c% f S+ j4 }8 O
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
X6 x5 l" W' ?3 w0 { 英文官网:http://koajs.com $ ]# Q Q" g1 A7 @( |, K
中文官网:http://koajs.cn 7 U. x& a' E* P0 f9 ~
1.koa
0 |0 m# {; U6 n( k 安装koa包: npm i -S koa@latest
1 {+ Q# x! @8 W 引入: const koa = require("koa"); 实例化对象: const app = new koa;
- s. n9 L" R4 p3 a 通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册
4 ]1 ?. a4 U0 u7 V! G5 l use()函数中必须使用异步 async; use可是调用无数次; , Y, _4 f7 I; m& B
其中有两个参数: 4 i5 E3 d3 d# ~! V9 y5 A
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
" m% u! E- l+ Y7 J# n6 g: v- a b)next: next(),将本次控制权交给下一个中间件。 6 \: Q* U( |+ p
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
# N1 T* R0 ?$ d4 b 1. next参数的使用demo
# ~8 q' M& c$ G# y! Z `const Koa = require(``"koa"``);`
0 b$ o: Q5 R7 ], u- ?: v) j `const koa =` `new` `Koa();`
. L V0 O( j0 q/ ~ k9 P `//中间件1`0 [, u" B j: x+ x' y0 C6 R/ |. X
`koa.use(async (ctx, next) => {`
9 t2 Z8 h$ J* q* o `console.log(``"1 , 接收请求控制权"``);`
/ L. ~6 P, D& a$ v `await next();` `//将控制权传给下一个中间件`
3 {/ \% e9 e$ e) [$ f& y& T `console.log(``"1 , 返回请求控制权"``);`0 u" r8 O; l; _* L
`});` `//将中间件注册到koa的实例上`2 M. q# |# b6 L* @; u2 F) V X/ D
`//中间件2`, N( O* _2 S$ l. f: P
`koa.use(async (ctx, next) => {`0 B4 [9 e( l) R) }
`console.log(``"2 , 接收请求控制权"``);`; J' _) s$ h0 |! J4 Z6 h. T# L( `
await next();`, ~" M) E# \4 }7 O, m2 L; j
`console.log(``"2 , 返回请求控制权"``);`
/ G0 B* n. L# a' N1 r `});`5 K, t+ k( N Q6 p5 ]3 g4 ?) G* H
`//中间件3`! Y; F5 ?) C; ?3 @
`koa.use(async (ctx, next) => {`
7 r6 R: U2 L: b0 _0 Q `console.log(``"3 , 接收请求控制权"``);`, A8 D0 D ], F* N5 b
`console.log(``"3 ,返回请求控制权"``);`- h4 }) N/ h5 m5 d
`});`! T: Y$ Q7 q2 ~1 \# l
`koa.listen(3000, ()=>{`9 y; A# h- V0 }* |
`console.log(``"开始监听3000端口"``);`
6 j4 q: {9 O; q `});`
! M# |8 U* E( x5 k R2 Y# }% H, J0 W 注:当中间件中没有next(),不会执行下面的中间件
' Z3 f* h: ^( t2 D- v 访问localhost:3000的效果图; 4 Z5 X: e( n n* Y) _ e, Z! G
( L4 c; c/ d' u) ] 注:会有两次操作是因为图标icon也会请求一次
5 b6 `$ u7 N- s: V! _$ P 2.ctx参数的使用demo
7 U' M/ ~8 q( a# @' t `const Koa = require(``"koa"``);`. R. u2 K) B# \; l+ D0 s' @
`const koa =` `new` `Koa();`5 B0 v3 Z d- r% }, E8 j
`koa.use(async (ctx, next)=>{`. K9 R: V( j# ]# j5 L0 g) ]
`ctx.body =` `"body可以返回数据,"``;`
w% N$ m- x+ O5 @+ o8 |& Q `ctx.body +=` `"可以多次调用,"``;`
a2 d! i8 a2 {7 y- w6 \ `ctx.body +=` `"不需要end()"``;` e1 [1 J* m1 _. |( m+ b4 |5 l" b+ k: N
`});`
# F6 [ X/ ~ L/ _3 S `koa.listen(3000, ()=>{`1 L, B' U& a0 {) r- @1 W
`console.log(``"监听开始"``);`- N- V6 Y6 z6 N: k
`});` # B. M" V* K4 l0 v t- L7 f+ `- \
效果: ! P: p8 d, [ b! _ r" b" F0 W
* L# B- L) Y/ ?4 f: t7 N3 D; m8 q* R ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
7 b" J( M$ U( V* P `const Koa = require(``"koa"``);`. w3 g, n8 m- P" `' ]
`const koa =` `new` `Koa();`
$ C& [7 w8 l4 x8 [, U1 G+ s, d `koa.use(async (ctx, next)=>{`$ y2 c; O+ |( K7 l3 v+ w0 s! p
`ctx.body = ctx.url;`
. W2 c- Z# s1 S- v `ctx.body = ctx.path;`
: x$ `' o. W! `; r/ n$ S% n" E: t `ctx.body = ctx.query;`
. u- _. ^6 u5 ~ `ctx.body = ctx.querystring;`
: l- ~( c( S) A" z `});`
: s" g0 I5 @+ [2 C `koa.listen(3000, ()=>{`
, G- g4 j* _$ F0 `. `2 X7 r `console.log(``"监听开始"``);`- y/ H! y: V' o, [, z0 f! P+ H4 P
`});`
# h5 O- s5 M& ?+ [+ N4 d0 r 访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
- ^, M5 m% `7 f6 X" l 1. url: 整个路径
+ g6 f5 ^/ r7 u2 a; N' x1 r& M / R" m, ~6 c) h2 F/ g x
2. path: 非查询部分 # k3 L: \9 w% a
' H6 j t! G) v$ X5 |- @) _' |
3. query: 将查询部分转为JSON对象 ( c6 X0 {4 a2 N- c
- t3 U4 s$ P: W7 X" d5 K
4. querystring: 将查询部分转为字符串
] S7 i# H8 d2 b4 p
" W. q' Y( H8 i 5. ctx.state ,ctx.type 表示状态吗和类型
- c, [, _, g8 Z% f- o3 i. Y 2.简单爬虫练习 3 }6 h _- `8 Q
安装request,cheerio模块 4 q$ {6 V* C: Y1 p
`npm i -S request: 请求模块`
) @- u( W, ` m: w1 l z `npm i -S cheerio: 抓取页面模块(JQ核心)` 6 C* {' l# d. {- |9 U/ b: u' Q
抓取网页数据案例(随机网页) " d/ R3 P4 D5 z3 r2 X- }
`//导入模块`; A4 C7 r4 Q R0 x, R7 E7 r/ X
`const request = require(``"superagent"``);` `//导入请求模块`
' D! {1 L( ~$ N; ~: }" D7 ~! [% s `const cheerio = require(``"cheerio"``);`
1 G* a U1 ?' U/ ?; P# t. y3 B `const {join} = require(``"path"``);`
: F( B" r# O: R" l" h% S `const fs = require(``"fs"``);`/ ?# W. [9 N# i6 D0 K& Y* c7 \5 m
`let arr = [],` `//存放数据` ]0 r- i( z$ b9 _- m. ]. X
`reg = /\n|\s+/g,` `//replace中使用`3 k' q3 q/ E( Z/ \- `
`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/)"``;`
0 z5 }; x9 o! O( \# x' M T3 i1 _ `request`: O) t. k7 p3 k' ^! M
`.get(url)`4 C! }- L! |8 M
`.end((err, res) => {`
; w0 x1 F! q: f9 \ ^6 _ `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
k+ d, b! n! R; m2 E9 C `$(``".course-item"``).each((i, v) => {`3 M6 P1 U$ A. m2 t
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`8 m, |5 d4 `( L3 o0 h8 P' l
`const obj = {`
/ n* `6 x8 D- ?8 A6 u! _ `imgSrc : $(v).find(``"img"``).prop(``"src"``),`( x( X$ p- V) j4 _* n F
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
& K) e% X0 x. N8 m `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`1 P( N0 V; k( l$ o' ?. Z
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
3 p5 e4 E+ G" A7 w% k `};`# B; U' `* i# }+ w0 j S+ U- ~
`console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`2 x1 U5 t( C" ]" {1 [$ i s2 M
`arr.push(obj);` `//把对象放进数组里`
; y6 {* v' J: D4 M- G: e2 ^ `});`
; u% z8 J' P' @/ |! Y5 c `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`
" v+ x. a, `* b1 f# A- C* c `});` ! M* Q) [6 T- D! a4 {0 x
以上就是本文的全部内容,希望对大家的学习有所帮助 % o' P# a- f0 T2 D* W
3 V( w1 o" K' p$ _- [
( {6 Z; X( {! o. B$ Q# {& T1 a1 D. B# E( v
; j5 P: i0 L- K% `$ R' y |