node.js学习笔记之koa框架和简单爬虫练习

[复制链接]
4 E0 e8 a2 m5 C2 f4 G3 _: h0 w9 ~

Koa -- 基于 Node.js 平台的下一代 web 开发框架

; a; b4 s& H0 D1 A1 G

koa是由 Express 原班人马打造的,致力于成为一个更小、更富有表现力、更健壮的 Web 框架。 使用 koa 编写 web 应用,可以免除重复繁琐的回调函数嵌套, 并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件, 它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。开发思路和express差不多,最大的特点就是可以避免异步嵌套。koa2利用ES7的async/await特性,极大的解决了我们在做nodejs开发的时候异步给我们带来的烦恼。

7 b1 A) j4 R) j# B. }5 ~! z% w# ]# t

英文官网:http://koajs.com

8 P' O4 E4 F ^/ p O0 }2 E4 a

中文官网:http://koajs.cn

/ d0 m* @2 m# { f0 q- ]

1.koa

4 Q# V/ o; e% o8 O& X5 W

安装koa包: npm i -S koa@latest

% W! y- e2 Y1 z0 G3 z

引入: const koa = require("koa");

实例化对象: const app = new koa; , ?; H8 j- O( }0 b% N! b- p" w/ X

通过实例操作,专门用于客户端请求的函数叫做中间件,使用use()注册

- w& a9 {0 I2 q. E

use()函数中必须使用异步 async; use可是调用无数次;

9 w* p! T7 T2 ?" @

其中有两个参数:

. Z6 d8 U2 [% }

a)ctx: 上下文环境,node的请求和响应对象,其中不建议使用node原生的req和res属性,使用koa封装的requset和response属性

# O6 ]4 C+ l4 \% O7 r m& U. D

b)next: next(),将本次控制权交给下一个中间件。

6 s& z4 W7 \6 e% m/ L) Z

最后一个中间件使用next()无意义,执行完控制权返回上一层,直至第一个。

' q$ A6 _; l1 k2 I

1. next参数的使用demo

+ Q( G& j( f# X; J" l8 b
`const Koa = require(``"koa"``);`" p" U" ^( Y$ ?/ L8 ~2 c `const koa =` `new` `Koa();` 7 x/ U7 D/ m) D$ ^7 M6 b `//中间件1`& K5 i9 P% F2 a0 q `koa.use(async (ctx, next) => {` 6 o1 _$ v' x$ m; C9 S `console.log(``"1 , 接收请求控制权"``);` J! M# g1 F) ~. C1 X `await next();` `//将控制权传给下一个中间件`) ~( Y; C* f# ~& O# @/ Q" }) @5 z `console.log(``"1 , 返回请求控制权"``);` 4 @3 g: V) Z( K5 a$ u$ Q `});` `//将中间件注册到koa的实例上` ) E# N; l8 V* B0 t1 a# g `//中间件2` 6 l. _+ I& {1 ?$ D# Q* W, J `koa.use(async (ctx, next) => {` 6 T0 T, I/ h2 r% M `console.log(``"2 , 接收请求控制权"``);`' R% j# ^2 `: w4 B await next();`3 O& ?& G: ], L S2 V& d! N+ f, e- ] `console.log(``"2 , 返回请求控制权"``);`0 m0 ], A. S. m8 ?6 C+ F+ H `});`- G+ C9 h$ E2 S/ H `//中间件3`* I* Q% b# S/ C3 F2 u- j/ X `koa.use(async (ctx, next) => {` 2 M2 s9 Y# z# {! u, {+ }$ t5 [ `console.log(``"3 , 接收请求控制权"``);`" E9 s0 H1 J% k' h$ X* ] `console.log(``"3 ,返回请求控制权"``);` Z. E+ h3 \, s2 t `});`/ Q6 J% `0 Y+ { O `koa.listen(3000, ()=>{`! J* P% {, Q- n+ ^- V `console.log(``"开始监听3000端口"``);`( d9 V; Z! V' A5 W- {' u) X `});`
. b' i$ E! ]' J: e% u' P7 o% d

注:当中间件中没有next(),不会执行下面的中间件

. {/ Y$ o+ j8 k

访问localhost:3000的效果图;

, S/ ?, b; O# ^' E
4 i5 r: R2 U/ ~' ?

注:会有两次操作是因为图标icon也会请求一次

/ X* |* ?7 o' G! R

2.ctx参数的使用demo

% d6 a8 ?3 t7 |. b8 |
`const Koa = require(``"koa"``);` - y1 `1 h8 ^5 f1 Z9 g4 I% K `const koa =` `new` `Koa();`( d z( @$ A! C4 Y; q `koa.use(async (ctx, next)=>{`: b) J; R8 D% ? `ctx.body =` `"body可以返回数据,"``;` L% a2 ^# K0 A7 e' E1 D9 x `ctx.body +=` `"可以多次调用,"``;` 6 Q0 e; c8 ^5 O, r9 t3 W# d `ctx.body +=` `"不需要end()"``;`+ f6 x) i: g* ?5 `7 G `});` + }/ ~, {3 L5 @; A- `0 s `koa.listen(3000, ()=>{`$ T6 C' [, @1 l2 ^+ `. d/ f `console.log(``"监听开始"``);` & n; z5 k! Y H3 f Q `});`
* o2 \ m6 o4 H

效果:

& B1 \, X4 S W5 T4 @
% d) J8 w# i9 ?- \+ }

ctx.url ,ctx.path ,ctx.query ,ctx.querystring ,ctx.state ,ctx.type

9 A& E. x, j4 a9 w: U# S% D) R3 `
`const Koa = require(``"koa"``);` " } c5 y7 P4 @* g5 L `const koa =` `new` `Koa();` , j+ L; k, c6 ]% B+ r4 M7 T( Y( E `koa.use(async (ctx, next)=>{`. b0 j+ ]2 O0 c `ctx.body = ctx.url;`) u7 @3 ?, V4 z `ctx.body = ctx.path;`; P* b) i) m( w2 y& i$ n8 h `ctx.body = ctx.query;` / d+ m1 m m3 Z% a `ctx.body = ctx.querystring;`; ]5 n1 I4 A6 H4 {4 L" } `});` * E: \0 {2 }7 d/ [% x" `0 M- B4 q `koa.listen(3000, ()=>{` 6 ?) C5 Q* W# z! a* J6 w `console.log(``"监听开始"``);` 6 p2 I$ ?' z" G9 O9 v3 K `});`
2 {3 X1 d% {6 f; V. M q. G

访问http://localhost:3000/path?name=sjl&age=18为例,效果图:

" G: ?( x: _6 B( \; {7 i

1. url: 整个路径

3 ^5 f; o, A& Y1 B6 t! V
7 N/ r6 ?+ L' `3 Y) F; W

2. path: 非查询部分

6 e, p8 R L2 W1 K6 x
% i' {- W: f+ W% S4 b9 W

3. query: 将查询部分转为JSON对象

4 E. p# u! e% }2 \, z
: \' w' I# g* n, A; ^

4. querystring: 将查询部分转为字符串

4 _) y7 g; p" a# D+ |3 d- O4 B% w
1 ~6 f2 c w( {6 I% j

5. ctx.state ,ctx.type 表示状态吗和类型

( Y4 z" O" Y) q# l8 k

2.简单爬虫练习

( [: C, @! s0 R$ N V- c4 }* j0 t, J

安装request,cheerio模块

3 V8 n2 e; C" v' M0 W
`npm i -S request: 请求模块` - g; i2 A8 t5 u- X. e `npm i -S cheerio: 抓取页面模块(JQ核心)`
7 [! p3 U% ?1 `0 D1 C; Q

抓取网页数据案例(随机网页)

6 B/ I% P& Q7 V' A: ]
`//导入模块`! W( j+ M# F- J- c0 K. F0 ?/ X# a) {; \ `const request = require(``"superagent"``);` `//导入请求模块`5 u' U! D$ k- t( E! g! B `const cheerio = require(``"cheerio"``);`- m8 s$ Y' M8 G# ~' X' u `const {join} = require(``"path"``);`! b9 V. H$ h, W* q% h `const fs = require(``"fs"``);`& Z u7 \" O6 N {# Y7 m$ _ `let arr = [],` `//存放数据`& ]/ i; u6 D4 t/ S, {6 X `reg = /\n|\s+/g,` `//replace中使用` ' I5 _( q0 o' R. }) f `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 d- z" o) r( j; `7 [9 d `request` % v9 W' u8 |2 ~ `.get(url)`6 X5 A+ h5 R, B$ W" v8 ^ `.end((err, res) => {` ( V' g0 t+ V) R$ t- t6 a `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用` 1 { Q; x; q+ F( }2 h `$(``".course-item"``).each((i, v) => {`: u" R* `1 Z1 r( w `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`$ s6 ^. v) J! `+ U) _' I `const obj = {`( v; n; h9 Q8 v5 j5 J! k `imgSrc : $(v).find(``"img"``).prop(``"src"``),` / S; d' H W5 V' J `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`9 O- z( j+ y7 y. _ `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` " w) k6 F& ]- i& l( b) G- ^& B( Y% u( I `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))` : H' `! t0 `" i( n; |# o; a `};`6 x# z' ~/ _% F. @' X. ? `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` 0 P2 r! C4 ]" ]) _8 e `arr.push(obj);` `//把对象放进数组里`/ w1 Q: g; y1 H, O# W' K, o `});` , [1 t. i; f7 F( Z `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`! B; \, a2 c: l# Y6 C; D `});`
5 X/ Y8 X+ G: b1 l1 q0 e

以上就是本文的全部内容,希望对大家的学习有所帮助

_* l! q9 J8 e/ P3 f7 { / g d, j3 J' Z" v, d7 s6 a( k/ Q2 a7 `* ?; Q 7 {8 g7 K1 C$ l" q' _# i4 s7 G1 R/ A2 l+ ^: |' `
回复

举报 使用道具

相关帖子

全部回帖
暂无回帖,快来参与回复吧
懒得打字?点击右侧快捷回复 【吾爱海洋论坛发文有奖】
您需要登录后才可以回帖 登录 | 立即注册
邢雷
活跃在2024-11-7
快速回复 返回顶部 返回列表