|
2 `9 X; s7 }2 a' ? S8 @
Koa -- 基于 Node.js 平台的下一代 web 开发框架
2 w4 `/ P0 V+ B) H3 Q# t; A7 j koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
/ D1 E7 J0 L, ]3 b# P& p 英文官网:http://koajs.com
; ~9 t, t9 e& v3 C) [ 中文官网:http://koajs.cn * ]! w7 c8 \! i" `' t$ R2 T
1.koa 3 _& r/ p s$ H& H \
安装koa包: npm i -S koa@latest . }! Y* @# E0 T( R" y# J+ S; y
引入: const koa = require("koa"); 实例化对象: const app = new koa;9 r! O, g! G; a" L- C5 R5 ]1 W
通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 # X C! V$ I' v# x! ?
use()函数中必须使用异步 async; use可是调用无数次; . q4 \* X2 d6 N, I( [2 T. h" @0 B8 Z
其中有两个参数: # S: x$ k, w% a; J# Q
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性 ) |" D* }) C0 M1 T! A u9 B
b)next: next(),将本次控制权交给下一个中间件。
% j! j7 d" S# x* Y5 i, u! o2 r, A3 S 最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。
2 }& {- e% t- H9 ~+ T, ~ 1. next参数的使用demo
% J, T$ N/ @: ?( S& H& f `const Koa = require(``"koa"``);`! ~9 |8 u+ p4 [# ?% U9 d
`const koa =` `new` `Koa();`
5 U, `8 g* K& o `//中间件1`
5 }) y$ Z# g' c: ?- B `koa.use(async (ctx, next) => {`
' B# q6 A" @2 s$ k# c2 ^ `console.log(``"1 , 接收请求控制权"``);`
- j* S" i9 ^. t) O2 D) Q( l/ q `await next();` `//将控制权传给下一个中间件`
" d! t& i J" G; ?: I) L' X; q `console.log(``"1 , 返回请求控制权"``);`
3 g0 x( C P: [1 e/ i, J! p1 x `});` `//将中间件注册到koa的实例上`
6 \" [1 K# f* b& s/ y `//中间件2`# }, E0 ] I O, T1 E- n
`koa.use(async (ctx, next) => {`" Y: @5 n% Z" }' F9 q' a
`console.log(``"2 , 接收请求控制权"``);`
" d' D8 ], q/ } await next();`/ i+ t( @6 l$ o* L8 X
`console.log(``"2 , 返回请求控制权"``);`
! f! [+ g" e, ~: a' B8 W# E `});`
2 }2 Q: D1 b, e' i `//中间件3`, G4 L. n! G1 R. }* `% g
`koa.use(async (ctx, next) => {`1 f$ z+ M8 B" e' ^8 [0 B
`console.log(``"3 , 接收请求控制权"``);`# j# v) P6 A! I0 L9 ?8 U& W5 t. m: u
`console.log(``"3 ,返回请求控制权"``);`! ~" v+ B5 q. A2 b& ~
`});`- ~( ^# r4 C" C' F1 _
`koa.listen(3000, ()=>{`7 S$ q( Y" q8 B X# m$ \
`console.log(``"开始监听3000端口"``);`
M; E; z! L" k `});` + S/ w( ~/ w$ K' V( N, j
注:当中间件中没有next(),不会执行下面的中间件
3 H' r. Z- I) V5 J. { v% g/ `/ i$ _" \ 访问localhost:3000的效果图; 4 I/ ?1 q; b3 F
) Q$ |" ?$ E* a
注:会有两次操作是因为图标icon也会请求一次
% K- o. F) z' z" D 2.ctx参数的使用demo ( A9 ] \ k# y% [; Z4 x7 ~
`const Koa = require(``"koa"``);`
0 \# z, W3 P& [/ X d `const koa =` `new` `Koa();`
0 |- p( G( W$ A6 a' B. e `koa.use(async (ctx, next)=>{`/ ?: D0 _2 `7 Y8 S, t( A- [' v
`ctx.body =` `"body可以返回数据,"``;`
! i. o2 `9 _2 Q; k9 ?0 S4 Q `ctx.body +=` `"可以多次调用,"``;`! m( D) L9 w6 f' k" w: M
`ctx.body +=` `"不需要end()"``;`( {! V3 W0 G/ t; e
`});`" g+ f" l1 Q( p) \
`koa.listen(3000, ()=>{`
/ @. E/ H8 X' x0 }# p1 l" C$ @% D7 E `console.log(``"监听开始"``);`
( w8 x4 G8 e: I T1 ] `});` 3 [: F+ u6 a+ W5 |: `
效果: & ~& ^7 f2 m& h" r4 w4 X8 T; c. P
8 N9 o d; U# U/ a' o9 i ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type
7 k. {/ A' V( h$ S- ^0 [ `const Koa = require(``"koa"``);`
$ C" N! b9 _; m' E6 r; U3 \ `const koa =` `new` `Koa();`
9 u( v" W# K4 N J) m1 [. L `koa.use(async (ctx, next)=>{`9 V6 p0 P# F, c& R) ]
`ctx.body = ctx.url;` ]# e* A, h$ o1 b
`ctx.body = ctx.path;`; W7 k+ k% i( N: J2 ?6 w- ?
`ctx.body = ctx.query;`
5 u( U9 z$ ]; _' U1 W `ctx.body = ctx.querystring;`, p2 H, o; [9 |
`});`6 k) y6 M, h9 y5 B7 S$ v
`koa.listen(3000, ()=>{`3 W, O$ @5 b, h) z; y3 ]
`console.log(``"监听开始"``);`
1 v s+ a: b }* y. K, d `});`
3 q* d: J: y- G `; u 访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
. o9 j8 S8 z+ w+ M! h' M P; G 1. url: 整个路径 1 h/ {, d! {& f/ |3 c
; k+ G. s4 \: M+ Q7 @# J 2. path: 非查询部分 ; z( V5 O2 J$ q1 z8 l6 W* f
$ R9 \+ d+ d6 |
3. query: 将查询部分转为JSON对象
! m, w2 ~) }4 b% b6 q1 d. o
; x0 f+ ^5 @6 ]- u6 K% V 4. querystring: 将查询部分转为字符串 ' l' `5 i' _8 W4 Q2 H) z
) J m, k) B1 b: E% q. ~9 L" X 5. ctx.state ,ctx.type 表示状态吗和类型
, {- I, A' s; c: N. h 2.简单爬虫练习
+ ?$ L2 T+ w) X' A8 O 安装request,cheerio模块
* f H0 O/ m, i3 P% { `npm i -S request: 请求模块`1 g! w* t5 [5 Y( L
`npm i -S cheerio: 抓取页面模块(JQ核心)` , l- Y# e) r/ W) r; \
抓取网页数据案例(随机网页)
\7 _7 C) z% q7 } `//导入模块`6 h6 ~$ n5 @1 F9 A& V5 ?# v
`const request = require(``"superagent"``);` `//导入请求模块`3 Z* s( K& `! b0 s6 {. U" \1 g7 o
`const cheerio = require(``"cheerio"``);`
: ]$ J' _+ S4 \$ g; ]4 k; I+ J8 n `const {join} = require(``"path"``);`
5 q; o9 x( L* U5 q2 Y `const fs = require(``"fs"``);`
2 z% a8 b( T: n+ i$ e `let arr = [],` `//存放数据`; C0 W+ p1 b7 U- S9 D% `
`reg = /\n|\s+/g,` `//replace中使用`
' `6 e7 P6 J% h* M+ Z, Q! q1 t `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/)"``;`
, {: _# Q* T; m3 [, O! | `request`9 p; {$ ^0 a/ K" E
`.get(url)`
7 X) v+ L8 { ~. G* s# d8 }* F m% Y `.end((err, res) => {`! ^( B! c2 s3 J7 R# ~
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`& q3 Z+ f3 {3 j' ]! z6 V3 |
`$(``".course-item"``).each((i, v) => {`4 c& i$ c6 u3 K- Y
`// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`3 ]: U% F6 u. z7 I: _
`const obj = {`
- i" O# i: E# O3 \& y" h9 h `imgSrc : $(v).find(``"img"``).prop(``"src"``),`
) |( W N3 Q7 Y& o0 [ `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`; x- ^9 R$ \$ w
`total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`1 o2 t& A) l6 z2 X' X
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
3 V, c+ J9 Y& c* y, E `};`
' z3 t( d7 g% v/ U. w; k( } `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`# k/ p2 Y" D+ n
`arr.push(obj);` `//把对象放进数组里`- B. ]- g& X4 e/ ?9 m6 k* x6 D+ I, G
`});`
# V5 _! s# a, w' V- L' g `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中` o' v0 e5 ~/ G$ A8 ^ f! k" l
`});` # w/ w% ]3 ]5 k1 I4 ~% U8 k7 l6 @
以上就是本文的全部内容,希望对大家的学习有所帮助 3 | c/ b0 w- G2 y
* v$ C- E1 D3 [' N0 p
9 v, M/ T! r# w% f9 B0 f7 j3 W+ I& Q0 f: l1 A
+ L1 ?2 s* h) I" @* d7 u0 X4 E3 d$ k |