8 f7 c1 W+ q5 N$ {/ C- H Koa -- 基于 Node.js 平台的下一代 web 开发框架 2 v6 C2 `7 q# k7 T& L# }
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。 / i( g. t7 }, i5 D1 R( T
英文官网:http://koajs.com
" b P6 F b4 G$ a. O6 ]/ K; ^ 中文官网:http://koajs.cn $ Z7 _8 a9 ^0 v: _
1.koa
. r Z& D5 y6 ~3 @# _. `: R 安装koa包: npm i -S koa@latest - I6 i6 Q2 v. ]+ y! O
引入: const koa = require("koa"); 实例化对象: const app = new koa;9 q3 ~8 q8 K, N4 ?; G# Q2 W3 c9 c
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册
. O6 O1 R( b. \+ T use()函数中必须使用异步 async; use可是调用无数次;
1 x- I0 b& x) Q 其中有两个参数:
& p% \2 Z; D7 ^$ h a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 c0 [) O5 F7 I' k" M
b)next: next(),将本次控制权交给下一个中间件。 0 p+ A" d7 ~% n* m9 H+ }+ r
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 : X1 G6 Q: x7 r! ]; ?- z
1. next参数的使用demo
' ~5 X$ D2 [7 v `const Koa = require(``"koa"``);`
/ w5 A0 j: k' R6 R `const koa =` `new` `Koa();`, e8 o$ @0 j, W9 d2 ^
`//中间件1`
! {; P6 ~2 c6 A `koa.use(async (ctx, next) => {`" l, J, u3 W* ]
`console.log(``"1 , 接收请求控制权"``);`
- j# w% f( _6 O: p2 Z `await next();` `//将控制权传给下一个中间件`3 v \6 r* b- S% w& [
`console.log(``"1 , 返回请求控制权"``);`
* o2 u l! h, y `});` `//将中间件注册到koa的实例上`8 g! _0 Z" B" v# F' K
`//中间件2`( l8 Y4 y% q+ o- n2 `
`koa.use(async (ctx, next) => {`0 k5 }1 y2 V3 S% I3 Z
`console.log(``"2 , 接收请求控制权"``);`
9 ~- ^$ _7 E) K* M await next();`( Z5 |! j+ I" x! V6 w! [
`console.log(``"2 , 返回请求控制权"``);`
* B: O5 B! o i0 m% {) h `});`
) _$ u! f# y1 N4 i% Y1 H* W3 o `//中间件3`: n( p; G$ Z' E, s6 `( [
`koa.use(async (ctx, next) => {`
+ Y' R+ o" ]( T# t$ t! U1 S( E `console.log(``"3 , 接收请求控制权"``);`/ _$ D1 V6 ^: Q
`console.log(``"3 ,返回请求控制权"``);`
/ i: J: o6 V) N7 R$ g0 D `});`" Z& U# o) v* e/ p2 ~! y
`koa.listen(3000, ()=>{`
# j" A8 Q. r) \1 M `console.log(``"开始监听3000端口"``);`
, z6 b4 T" i! a" w- b, k3 c `});` + y7 M" O- a; X' F# V; K
注:当中间件中没有next(),不会执行下面的中间件
! X4 L" ^0 M& F& S6 M$ O2 E+ v( | 访问localhost:3000的效果图;
% w6 }1 j- g8 k , t; ^0 [3 Y6 l1 v. {" @6 I
注:会有两次操作是因为图标icon也会请求一次 / ?& E- {2 n! X7 H4 u! [- L
2.ctx参数的使用demo ! Y+ G& k3 A. j! S
`const Koa = require(``"koa"``);`
! k' q V3 l/ t I. c) j; b `const koa =` `new` `Koa();`7 N$ o* l' g" L, s* ^
`koa.use(async (ctx, next)=>{`
- R7 X" d' l5 r3 V `ctx.body =` `"body可以返回数据,"``;`
# @7 {- d k; ?# M! u `ctx.body +=` `"可以多次调用,"``;`
- l% ?. Q( Q8 E3 F7 }% l, Q( x `ctx.body +=` `"不需要end()"``;`1 H5 U: _% \$ m% w, w
`});`" A$ M1 s/ G1 C% D7 p* S8 H& B
`koa.listen(3000, ()=>{`
, h9 ?& b& P" m% k S `console.log(``"监听开始"``);`
, z4 X4 O4 W: V& }/ Z `});`
5 A+ ]6 }* z4 |$ Z) Q 效果: 1 y* Z2 i2 ~: e% O2 {; P% ~) W9 Y
4 w& i5 T5 H3 t( `/ r ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
' c9 ]2 w+ N( m6 l! t `const Koa = require(``"koa"``);`( V" y1 u' Z, Z: z( ?- A o g
`const koa =` `new` `Koa();`
: P* W# a2 T4 s4 b `koa.use(async (ctx, next)=>{`
2 P1 r( e9 q# G, M0 z; f% L+ h9 d `ctx.body = ctx.url;`
: G; z) H: e& {8 J' d8 `" W- j `ctx.body = ctx.path;`9 p: h8 o: p! A& y- a: f8 _
`ctx.body = ctx.query;`2 F- B" s' c6 w' c& R
`ctx.body = ctx.querystring;`
; u9 o$ S* I& o/ v4 y2 g- k `});`
0 ^! v; M) q! a! e `koa.listen(3000, ()=>{`! Q3 A9 n1 U4 Z$ @ U4 L) \
`console.log(``"监听开始"``);`
! j* }" K; P0 R+ D `});`
" L6 x; F* b+ l$ R4 V3 ]0 [( d 访问http://localhost:3000/path?name=sjl&age=18为例,效果图: - M! y2 G0 `* W
1. url: 整个路径
- g! Q( ^7 J$ d; X5 J% @2 W! L: v + d) [" h! X2 z2 ^# ^
2. path: 非查询部分 : f2 k* o- K) ~
( y" Z( F f& R1 v1 n' ]
3. query: 将查询部分转为JSON对象 & v0 j8 a& B5 x( V# i1 u
% n( H2 w+ w) L 4. querystring: 将查询部分转为字符串
; {# X) v$ ~3 @- O+ ]. q9 R1 G
' M6 S- V* R9 X5 C& A( E 5. ctx.state ,ctx.type 表示状态吗和类型
) E+ r( c/ m, n* y 2.简单爬虫练习 8 u& r9 K7 U7 J
安装request,cheerio模块
; D+ c3 A' z% z# z7 O7 \ `npm i -S request: 请求模块`
3 Y5 Y0 F6 q/ h' T6 b `npm i -S cheerio: 抓取页面模块(JQ核心)`
0 P- ?/ R; [+ H( R 抓取网页数据案例(随机网页) 4 ?3 f, \# ]( b. M
`//导入模块`: p P/ E6 g2 {: X5 W2 p
`const request = require(``"superagent"``);` `//导入请求模块`
$ `; ]$ d4 J ]; K `const cheerio = require(``"cheerio"``);`
* ^2 A8 [7 G1 T; H; f0 q6 K# I `const {join} = require(``"path"``);`
( c* O( G! `8 ] `const fs = require(``"fs"``);`
; |+ s) e ~- }% O. E `let arr = [],` `//存放数据`
! Q: J5 K6 F1 ^9 i `reg = /\n|\s+/g,` `//replace中使用`8 K* U7 u8 Q. I. s& U
`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/)"``;`
$ \' T) v: ]+ N `request` X7 L$ \4 ~ A% ?/ [
`.get(url)`
! \ Y4 `3 a. X# t4 [' v `.end((err, res) => {`( w! [4 I: F, }6 v
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
9 I( u' O( p" K* J3 p4 [ | `$(``".course-item"``).each((i, v) => {`% x( a, |& {. {. o: X
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`
# m: O- Z# S+ d( e `const obj = {`
, ?6 K- J7 V# _; }. W9 t `imgSrc : $(v).find(``"img"``).prop(``"src"``),`% f4 B8 B8 p$ N9 f7 Z8 M) F" r
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`8 ]7 H: J, ]( m- ?+ {
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`
% T; s/ b" \, ?+ e3 U: x `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
# s6 s0 v4 O8 h' g" |0 ?1 z `};`& z9 E8 x0 M: p8 j' y
`console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`# }" b' [/ V6 n. }& P
`arr.push(obj);` `//把对象放进数组里`2 w4 F5 U H/ }- `
`});`
0 C' y9 V+ Q( @6 @" ~" u1 { `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`
J- f5 e, s: Y' v( r `});` 4 t$ y; e u5 s, z& j2 G# h6 x
以上就是本文的全部内容,希望对大家的学习有所帮助 7 m- ?& i( i+ _9 j7 c& d
1 d. t' A" O" j2 |, j/ F+ X
; m9 q+ V1 T+ v0 w7 w5 N+ K |
2 o2 R; Q! k p* H4 Z* J" X$ }# _/ n" \
|