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

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

[复制链接]
& z1 Z" }+ |- G0 |5 Y* k% R) E

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

0 l# y1 s& D: q4 J L

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

2 E1 z/ P3 U, P8 y4 v: O

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

! U i# v4 g2 w1 ~

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

# J$ t) b$ i/ A

1.koa

- {( k& y4 Q3 O. a

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

- O- e q! y' y

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

实例化对象: const app = new koa;* U5 U* c" u* j

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

8 {$ i$ @7 B$ w" G% W; f+ k

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

8 {5 } N- d8 t& M" j8 X. _; J

其中有两个参数:

- K+ {# V$ l \8 J4 \% T! F

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

. y) F6 E. T( K# R: t& Z' I

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

! F- o0 u' c' T" Y. v3 I! n; x) g

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

[. V5 G/ c- p: v. M

1. next参数的使用demo

" v/ a% U/ m& w& u# ?
`const Koa = require(``"koa"``);` ; S1 F! `. m; K! u& M3 Y `const koa =` `new` `Koa();`5 R/ l2 e2 _1 o }) w; `/ D `//中间件1`, T2 \$ `! t; V3 F `koa.use(async (ctx, next) => {`) ~" T+ F: ]4 t' ] `console.log(``"1 , 接收请求控制权"``);`- x7 w7 a6 y$ R$ N$ w" B# y0 } `await next();` `//将控制权传给下一个中间件`, v8 D% h2 X9 N i1 w! I `console.log(``"1 , 返回请求控制权"``);`! ]- Y7 o& c, d4 C1 n) }+ J `});` `//将中间件注册到koa的实例上` 6 I& s$ O2 F2 }7 @2 x `//中间件2` 4 {) w! ~) u* H5 }% `& U% y `koa.use(async (ctx, next) => {`& ^0 @# f% O$ Y7 A6 @* \ `console.log(``"2 , 接收请求控制权"``);`1 D t0 j7 ^& A& k% ?5 E, {% s9 i$ G- y await next();` " X. N' v! X- l6 o `console.log(``"2 , 返回请求控制权"``);`# e7 i5 x% s+ ~3 \ `});`6 p) T$ n" |! m; |4 \( w `//中间件3` ' ?7 h3 B( l. f: @ `koa.use(async (ctx, next) => {`! d5 v. E" S, y `console.log(``"3 , 接收请求控制权"``);` 3 ^ [8 z _) } `console.log(``"3 ,返回请求控制权"``);`3 x$ e8 H) i( M B) s+ k `});` ( Z" E2 w: R8 \. @% y- t& v `koa.listen(3000, ()=>{`. ?& F; C3 T/ ^$ C9 b8 h `console.log(``"开始监听3000端口"``);`8 h6 z, W9 g( X4 g4 Q `});`
Y* s, R1 M% j3 _7 ^+ R# b9 ]4 s

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

% c ^4 d: \9 u( G! G

访问localhost:3000的效果图;

7 b) \8 W. n K! j4 ?! J
7 |. l4 F9 a/ x) x. B

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

* s* A) U; Z) l. @( Z

2.ctx参数的使用demo

7 i9 V+ H. Z; b" F8 f$ ^6 a) l; o* T
`const Koa = require(``"koa"``);`& ]' s! D4 V; i& J `const koa =` `new` `Koa();`0 _* B+ M5 o5 b* d) F `koa.use(async (ctx, next)=>{`2 \( _" O+ }" N" v4 \& v `ctx.body =` `"body可以返回数据,"``;`( U5 }, ~) f2 P `ctx.body +=` `"可以多次调用,"``;`; p, U2 {0 \+ F) q" C2 S' R `ctx.body +=` `"不需要end()"``;` , p7 K9 |# U- r$ z) b `});`+ X; _# V4 l/ r/ i7 g `koa.listen(3000, ()=>{`1 K# y/ @) B4 d" A U1 ?1 E5 E5 d `console.log(``"监听开始"``);` , P [. x; K! y. h5 X7 S1 p, s `});`
- q. D8 U; z) X

效果:

3 b7 O9 C0 I1 P8 d' y
/ d" P, t- e$ G1 c

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

. i3 P6 E3 a$ z: [0 C
`const Koa = require(``"koa"``);` / N9 ^& L+ x$ V: b `const koa =` `new` `Koa();`, Y6 m* f) `6 R5 w. F, A! X# c: k `koa.use(async (ctx, next)=>{`7 n- \) f: }3 N2 o+ ^; _) a# i+ C `ctx.body = ctx.url;` 9 V+ K( s+ w% L! [ `ctx.body = ctx.path;` , f) P" j: \2 y `ctx.body = ctx.query;` S6 L# S/ z8 u- t0 K. ~ `ctx.body = ctx.querystring;`- h- c3 v: ^+ U- u ^. g `});`0 @; {0 G( L2 v! W6 N4 s `koa.listen(3000, ()=>{`- D) K" M6 A# ]7 I# h3 Z, h `console.log(``"监听开始"``);` 1 e" `6 S2 H4 e1 f- f# i, h `});`
, H2 d% W" F* J6 {

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

& u9 _$ B2 N9 t8 j3 Q% ?# f

1. url: 整个路径

) F7 ~) a9 Y: o& z3 ^! I
2 c: g7 Z/ _7 u% P

2. path: 非查询部分

) ^, S3 S! }7 |- L1 i
3 S3 T& `1 o+ G* p! j0 S

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

8 k! D3 F" l" z
, I# j* r- a- u- l

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

. n- l+ T3 b7 D5 {* u. B2 K) M! x: N* `
' ~1 k2 X1 R* B l8 r1 C) ^

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

" S! G, a W2 P

2.简单爬虫练习

/ d# o- m7 m% s& J o4 h7 }! W

安装request,cheerio模块

7 n, {6 L3 S9 d1 \/ A; u
`npm i -S request: 请求模块` ( ?( K6 i- N) s6 e m `npm i -S cheerio: 抓取页面模块(JQ核心)`
" O9 y- x: Q9 m0 m2 ~9 H

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

# r8 ^. T' z0 m0 a! J9 K
`//导入模块` 6 ?9 f! Z" w! b/ `+ Q `const request = require(``"superagent"``);` `//导入请求模块`- W- b' B0 \+ I6 K, R' p* F' ^ `const cheerio = require(``"cheerio"``);`8 p( {: R6 g7 b( X `const {join} = require(``"path"``);` / |: S) w0 |7 G# g/ S `const fs = require(``"fs"``);` ' I; x) D1 e$ ]2 A$ c" \ `let arr = [],` `//存放数据` ; s" a) `" ?* y0 ^- n `reg = /\n|\s+/g,` `//replace中使用`6 l% l1 B3 S3 Z4 _6 w' l `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/)"``;` ) K) w9 ?/ g4 a `request` 3 H+ x- E9 D9 k$ V/ V0 _2 v `.get(url)` $ a5 i2 H! ?# l2 ~& _- Z7 ` E4 u `.end((err, res) => {`$ D( P/ G" o& ^" j `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`; z0 a+ ]4 _' q+ M5 d `$(``".course-item"``).each((i, v) => {`' R; _& J2 r# n3 W2 I `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`1 c6 q! h. l w! Q `const obj = {` 4 }4 Q" I* V+ O+ Y `imgSrc : $(v).find(``"img"``).prop(``"src"``),`1 p! m7 L% x8 Q3 R( [( _+ O9 k `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),` ; [7 D+ l8 L( f* ] `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`( F9 `& F8 _) N `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`% u. y1 N9 h0 }* E" L `};` ! ^% t; @6 T, Q3 ]' v `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`& ~1 l. v& g' p7 _) Q! K `arr.push(obj);` `//把对象放进数组里` ! B' c- V. q4 G6 ]! a `});` 6 ?! T1 O* J8 E4 k: R, e `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`' G8 R& x2 _$ ~. X6 ?/ A, d8 X Q, V1 _ `});`
5 X& H/ c" E, w4 `" w, O. e+ F

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

7 J- K0 Z* P# | h) y 0 A/ C3 l$ j( H* \5 i5 X1 Z3 M: Q. _0 } 5 F$ J' c- ]/ e" `% H% |) s: ~* s" J: ^, r- z" Z- ?* s
回复

举报 使用道具

相关帖子

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