|
- U/ l: U5 `9 Y' w6 H
Koa -- 基于 Node.js 平台的下一代 web 开发框架 9 O7 m% S& k7 t* ?0 ~- O( U& s9 b
koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。
+ }/ k) z2 N6 q 英文官网:http://koajs.com . M" e+ |. z6 J$ j+ \# a' P
中文官网:http://koajs.cn ' j4 g; ~8 Q8 l8 e
1.koa , Q- \5 C' R( ~5 m
安装koa包: npm i -S koa@latest 7 |& h& a% u0 X2 {
引入: const koa = require("koa"); 实例化对象: const app = new koa;
* i7 R- j5 V- y- ]! p; q" Z7 q 通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册 7 D o2 R0 g( h2 y# O0 p
use()函数中必须使用异步 async; use可是调用无数次; 6 }9 c' m7 ~% B" d* r2 x" N
其中有两个参数: 2 S8 p" F( M* D# p3 f
a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性
g1 C$ H3 N6 L+ V, ~1 P6 w b)next: next(),将本次控制权交给下一个中间件。 8 G1 g; p) F8 Y* _) ` f
最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。 - G p7 f/ N* C8 d+ z
1. next参数的使用demo
# p- n" z# n6 @+ b+ M `const Koa = require(``"koa"``);`% U, N& J# u$ [& v9 ?
`const koa =` `new` `Koa();`. a- t( U1 p* A
`//中间件1`7 Y8 J; B1 q, }% p. z6 P
`koa.use(async (ctx, next) => {`; Y) \4 a$ d! }. B8 q
`console.log(``"1 , 接收请求控制权"``);`2 u1 U. g! Z/ |4 [3 L ~
`await next();` `//将控制权传给下一个中间件`
, L7 ]* z# ?" h# f( a `console.log(``"1 , 返回请求控制权"``);`
' n/ V7 c. C/ l1 F3 n; d `});` `//将中间件注册到koa的实例上`
& X' I) y, X8 e" F4 x `//中间件2`' h- @" Z& b7 W( D, {
`koa.use(async (ctx, next) => {`
5 q' b" J3 j( ]" O3 p `console.log(``"2 , 接收请求控制权"``);`4 V; l1 h2 `% O# s
await next();`
1 i0 k3 k1 ]3 C6 ?1 P% H `console.log(``"2 , 返回请求控制权"``);`/ t" A. v+ P, L$ P/ G+ d
`});`
9 R6 U) g4 P1 i3 e3 \ `//中间件3`
/ t$ r- D0 W; ^! Y( s `koa.use(async (ctx, next) => {`. K! h# `4 s0 l7 c7 I9 a. ^8 J3 @& C; H
`console.log(``"3 , 接收请求控制权"``);`( g3 @( m. Y' Z
`console.log(``"3 ,返回请求控制权"``);`
- Y! E2 i8 X. I) y4 R; K+ B \ `});`
" [/ \# c% F2 g! j" X `koa.listen(3000, ()=>{`
: F5 X# c' M2 d- S- A8 k `console.log(``"开始监听3000端口"``);`
; V# u1 O1 P6 F6 f0 U `});`
: ~" n6 f x( S; p6 Z 注:当中间件中没有next(),不会执行下面的中间件 + ~ z+ T$ e" v1 J% s
访问localhost:3000的效果图; 8 y; m( {9 |! d4 D- y9 @
: A, y5 i N$ F4 N: ?% Q
注:会有两次操作是因为图标icon也会请求一次
9 n- X6 m( Z( n* Y! J/ l! E" V 2.ctx参数的使用demo R( g6 t( ?# ]* G
`const Koa = require(``"koa"``);`. X$ S6 Q' l' W P7 U
`const koa =` `new` `Koa();`8 ~/ B' l2 X J- S' N7 n
`koa.use(async (ctx, next)=>{`
0 b" y8 i* `1 f& b5 @1 g `ctx.body =` `"body可以返回数据,"``;`% q; x1 `7 j; F! I+ |
`ctx.body +=` `"可以多次调用,"``;`* a8 j7 c1 O+ Q r" e. R6 g
`ctx.body +=` `"不需要end()"``;`7 x* ], z0 P6 P; ?. s! F
`});`& g+ i4 N1 p$ _: ]
`koa.listen(3000, ()=>{`. T) y8 ^: ^1 e" H
`console.log(``"监听开始"``);`
' W6 A0 V8 k' n+ ~3 T `});` 8 R m0 ]* J8 m# s5 Q$ ^! y* E
效果:
% C/ ]$ I2 K' T* V6 Q ( A1 J! ?& ?2 a$ j3 b2 |' c
ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type 9 Q1 \4 a& D6 @ r: `
`const Koa = require(``"koa"``);`
, ]- u5 T- A: t7 c/ z1 b `const koa =` `new` `Koa();`
9 t3 w8 I: Q" L7 y- C1 F1 [ `koa.use(async (ctx, next)=>{`
; L: A0 y4 C3 ]$ K8 K `ctx.body = ctx.url;`9 F) [$ ^5 E9 p. j/ F+ i
`ctx.body = ctx.path;`
' [9 a4 {2 L' n; {/ O" P `ctx.body = ctx.query;`
$ v- A# r( t2 d. @. N O) O8 b `ctx.body = ctx.querystring;`
+ l/ q( l w# d- L5 s `});`
# [# Q6 w/ D3 _ `koa.listen(3000, ()=>{`5 ]' W6 B+ _" v! z4 u/ Y2 S1 e
`console.log(``"监听开始"``);`& F" j. H: Z+ k; L
`});` 0 Z6 V L" W1 v E5 {
访问http://localhost:3000/path?name=sjl&age=18为例,效果图:
0 Y5 \) z3 g, h' M) x) ^# M 1. url: 整个路径
% q" B# Z- o* e ; A6 Z# f# G2 Z3 C
2. path: 非查询部分
: |# X5 Y& w& Z: x2 J5 f% x
# e1 G7 w; `& h9 m* H5 x& T+ ?1 B 3. query: 将查询部分转为JSON对象
5 g" N; E6 k# L9 J4 y
% O: v4 D/ ?! b- b 4. querystring: 将查询部分转为字符串 0 Z* d- f+ H' {7 ], M
?! P5 P4 L* k, S9 ` 5. ctx.state ,ctx.type 表示状态吗和类型 + M- S9 X; a7 p2 {' {
2.简单爬虫练习 . ?7 Q) p# ^: J( {. {( j
安装request,cheerio模块 ( E2 k0 i3 p6 M5 _" L5 l# J( _
`npm i -S request: 请求模块`# @/ b2 v1 e* K+ G; x- e
`npm i -S cheerio: 抓取页面模块(JQ核心)`
) A# h. e! |2 |% F6 O/ w 抓取网页数据案例(随机网页)
& {& g. z* u {- h `//导入模块`
9 h& A: j& _9 R7 P, K5 ^ `const request = require(``"superagent"``);` `//导入请求模块`
5 ^5 E, U5 z# q1 c; t/ w `const cheerio = require(``"cheerio"``);`* U* e. Q8 Q" P1 c2 R
`const {join} = require(``"path"``);`! d# x, r) Y0 N, k/ h' A
`const fs = require(``"fs"``);`
% i7 }& ~$ \* ]2 c" D) r `let arr = [],` `//存放数据`. a% s3 u/ u& t6 B: K
`reg = /\n|\s+/g,` `//replace中使用`) l$ `# v+ u1 H, j
`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/)"``;`7 Y5 `# m3 F) }, Z$ C' v" G
`request` U" }* m3 M# s( e F: r. x
`.get(url)`% {$ N2 @) V$ L0 \4 C
`.end((err, res) => {`8 t7 V, t0 U: G) f9 v
`const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`
; T+ q& b( w2 M9 D0 Y3 M `$(``".course-item"``).each((i, v) => {`
" n; f/ f6 V+ c! w8 O `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`5 `$ h# v0 z/ e# [, w. F7 D
`const obj = {`
! B0 N, _$ t5 T `imgSrc : $(v).find(``"img"``).prop(``"src"``),`) n T# \& C' [# i
`price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`
* H; [ \, d2 F% d2 O9 s7 r `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`% r. l+ G2 L& w' f4 L+ f+ b
`href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`
3 t5 G0 ~3 ?6 b6 D$ f+ _ `};`8 j9 [% G" d s3 m% p) }5 G5 p i
`console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`* y) r* B. `8 b/ ~2 g/ d' T+ h
`arr.push(obj);` `//把对象放进数组里`
3 r/ D" j7 a; D* \7 L `});`
5 }; b, x* m* u9 s+ R, b$ u `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`* o2 T/ H( Y" Y
`});`
; s* B( Q7 e) @' y ? 以上就是本文的全部内容,希望对大家的学习有所帮助 $ j! w9 N# [; H. e! x3 s3 K
9 y5 |- s) n) @6 t B- J/ ^
, h, L) Y4 e! b& D+ }
/ m c5 K/ X+ r4 Y2 U6 w5 z: E* \# U4 O3 B
|