收藏本站 劰载中...网站公告 | 吾爱海洋论坛交流QQ群:835383472

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

[复制链接]
2 c# a. l5 \! D1 Y8 a. s

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

9 F& }, r4 }, D+ J0 C

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

& d/ r' ^0 O+ B! G

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

/ V1 i6 J8 L2 e3 E

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

1 ~, U. S% v. f `' S$ [( w% _1 H

1.koa

1 t; k/ s; Q# E7 W

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

+ T# f' C* y: I9 o& |/ w9 f- ?

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

实例化对象: const app = new koa;3 A& u, {- Q5 O$ e

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

5 ^6 v8 N; y8 x) E: b' x

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

6 x7 T) _5 Z- |" L, Y

其中有两个参数:

$ [* ]9 o' K- g0 O. U

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

2 i, Q3 A Y+ N0 m6 c; i/ V: J

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

. A/ c. Y0 I/ _6 m0 m

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

1 @. D0 y5 l3 r! } \5 a

1. next参数的使用demo

. t6 \! p$ D/ `
`const Koa = require(``"koa"``);` L2 n1 p$ i" P7 Z8 M' r) j& ]2 I `const koa =` `new` `Koa();` $ x% {8 {) ^" g! o+ L0 I( F `//中间件1` / _# P. z; T/ ?; }2 @- | `koa.use(async (ctx, next) => {` & Y& C! Z* v& [; b/ d0 M" u; l' _ `console.log(``"1 , 接收请求控制权"``);`5 O: k: B1 J) n" I( T `await next();` `//将控制权传给下一个中间件`4 z! C5 w- o% E3 P2 D `console.log(``"1 , 返回请求控制权"``);`6 b i% h) r* t; e* E `});` `//将中间件注册到koa的实例上` ( i( V9 h8 r3 [ `//中间件2` 0 n; i. I1 h- u0 p V `koa.use(async (ctx, next) => {` 8 j8 n5 ?3 T! Q. Q; }- l `console.log(``"2 , 接收请求控制权"``);`, c1 h. I: K. ]3 T+ I6 y* v5 e7 H await next();` d" X5 T" Y' u5 |/ _/ v `console.log(``"2 , 返回请求控制权"``);` # P9 w7 N8 f8 Z `});` ( e! C) G3 L) d: S; f7 r `//中间件3` + v0 b k1 g t1 m4 i$ u) d* F `koa.use(async (ctx, next) => {`% `6 G5 {9 }" I* S1 z `console.log(``"3 , 接收请求控制权"``);` " U7 q( W% a5 J. S `console.log(``"3 ,返回请求控制权"``);`4 f$ y: ~5 z. b+ U `});` % h2 b3 l' ?1 o8 ] `koa.listen(3000, ()=>{`/ w8 G! @" }) J7 u `console.log(``"开始监听3000端口"``);` ' L( n* E2 J+ e! C/ P `});`
4 L/ i' p9 C2 T) |; R

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

% U- ?' B) Z1 b" b$ c0 ^

访问localhost:3000的效果图;

z/ a: U& _" N9 r2 b6 n7 _$ ~
' u2 ]* J" B6 m2 G' f

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

2 [/ s5 l, Q% h$ S: m

2.ctx参数的使用demo

2 }; b0 V- e% }2 J6 }* i0 @
`const Koa = require(``"koa"``);` 5 _7 z i* [& }! Z, g1 {) v `const koa =` `new` `Koa();`5 J& _! y1 u1 s; c6 J `koa.use(async (ctx, next)=>{`0 F5 I* N, E7 x6 Q `ctx.body =` `"body可以返回数据,"``;`0 T7 f$ e( o. y0 q0 H& D `ctx.body +=` `"可以多次调用,"``;`, ^& N$ F; c6 ]% {+ i `ctx.body +=` `"不需要end()"``;`" f" {7 j' h8 Y4 w4 C `});` 8 |& p. e6 |4 z& t4 I `koa.listen(3000, ()=>{`, y( _. r4 V& G% d2 A+ D `console.log(``"监听开始"``);`4 c( m, a# {# p- e9 O1 L* z1 o! K `});`
" u4 B- t7 K% A( ^- g

效果:

( T9 |3 |8 F( H; G4 l: r3 f- B/ \ C7 c
/ }. }5 w7 a- Y3 |" f& u/ z

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

6 i4 Y& Z. \9 W [8 Q
`const Koa = require(``"koa"``);` 4 T5 w2 {( U* ^0 D; W+ w m `const koa =` `new` `Koa();`8 n: K& M; S: @. H$ p `koa.use(async (ctx, next)=>{`) y8 T" U; R6 ^( k' F `ctx.body = ctx.url;` 3 P3 t& o' o2 A& x3 e `ctx.body = ctx.path;` 8 d' `) u; I& ^6 S9 f `ctx.body = ctx.query;`+ N* l6 O' g0 N7 x$ j, i' A3 H `ctx.body = ctx.querystring;`# s$ L5 K2 k$ T5 J1 Y& J `});`- [; f/ E9 d; j- R" S( S! [. E# S+ ? `koa.listen(3000, ()=>{` & |- \: C0 D' v% p `console.log(``"监听开始"``);` ; `. j2 n" w( n; _ `});`
) Z9 m5 P0 m9 R2 @1 A! c" {' J

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

8 _) s, I: q0 _

1. url: 整个路径

) p4 [- l. p4 r3 r. q+ ?: a, Y3 u
M5 q$ {$ s0 x& t# X7 |

2. path: 非查询部分

: V+ [2 S! ^ _( F5 m6 R
7 ^2 I5 y+ X: I& d

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

( Q1 b( b. y3 h' @ b& I
4 @$ j( t! m; K/ |, ? L+ B1 q

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

6 c' J+ a5 c* |# E! a- x- w" L- u
5 b0 t+ P# E: W y8 s" D

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

+ w% V u- m0 B( P4 ~8 M. \

2.简单爬虫练习

9 G9 Q4 D/ F8 y8 j6 M$ p: w6 E- e7 b. e

安装request,cheerio模块

; D, ?5 ^ T( e7 {6 N* F8 t3 j: d( b
`npm i -S request: 请求模块`4 l: _9 [! a( o! z( u {) j `npm i -S cheerio: 抓取页面模块(JQ核心)`
$ C7 N/ N7 s; G* ~% A

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

' v; W9 ^/ \! O, l) @
`//导入模块` G4 E! T0 x4 Y5 Q `const request = require(``"superagent"``);` `//导入请求模块`) a/ R: T) g; S- W& H' j `const cheerio = require(``"cheerio"``);`' z' |5 ]- D v1 r: b- Z* h* i `const {join} = require(``"path"``);` ( b3 m7 A" ?) ^7 @! x$ r# B! R `const fs = require(``"fs"``);` ' O! Q+ _% S E9 o0 { `let arr = [],` `//存放数据`, q- J3 i; }8 B% i* P) s) c8 A) J2 ` `reg = /\n|\s+/g,` `//replace中使用` . f! `! I3 E& F B `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/)"``;` ( g7 Y% _. q6 _7 Y1 z/ L `request` 4 g, C0 q, h& D6 n! S! R `.get(url)`) U5 W/ J: M, l, X7 L `.end((err, res) => {` 0 r. @; m' }6 D& ^ `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用` # ]0 q+ y7 g- ]% B, t7 D `$(``".course-item"``).each((i, v) => {`; J$ E! i* S% q6 V% N( o `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` 9 M8 B) F. Y+ K* [7 k* m! M1 f, O2 T7 ] `const obj = {`: C- g4 G% c b8 J `imgSrc : $(v).find(``"img"``).prop(``"src"``),`* O2 K& l1 N( Y `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`! P2 ^$ n( |/ Z. o* B8 } `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`; v& l0 D) V, B& y; { `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`% c0 F+ r" x4 E1 z1 U. ?$ l `};` 2 e' v0 I5 x' C; S0 i9 B4 b `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` & X0 a' w( U' b3 Z1 g8 ]( m `arr.push(obj);` `//把对象放进数组里`, [) }& u6 K4 {$ \/ a$ A; j( Y4 I `});`& i* a& j5 ?4 j6 O. _" ~+ K `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`* J6 @/ m% X! c3 z) z `});`
p9 N3 t% J0 y; H

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

% d6 P- P# f; k: E 0 J7 z( E2 c; c1 [5 y' o 6 x, J6 ]: ^- y, x) [ 7 k4 r) L2 U9 l, ^2 B4 |5 N) F r G6 q! A
回复

举报 使用道具

相关帖子

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