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

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

[复制链接]
- z, F D. n% N+ |; C' W

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

) w4 W \0 B9 I/ n5 j A7 R& T

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

' b1 g6 v: x5 ?5 s# n

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

3 F) S9 E1 ^# {% i2 t7 d

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

6 f# D( l9 ]; B! s

1.koa

. v p8 j' ? o; f

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

6 P" j( t' \3 l t

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

实例化对象: const app = new koa; 2 s5 F0 V, ^4 B+ `, X/ D2 [( b B

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

9 X4 j2 w* O/ j0 _3 v5 @

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

/ _9 g: ~* i- ?6 m, ~1 S6 f

其中有两个参数:

! W5 u" I# q) E l7 R

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

, F" U2 y+ v* k' d; s/ s$ p- X

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

' c* ~- j( x! L. P9 L0 E

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

# Z9 G, W! S7 d q3 G$ R

1. next参数的使用demo

' F$ I h7 h4 R
`const Koa = require(``"koa"``);`+ y( r' F0 ]. d* @ `const koa =` `new` `Koa();`: d$ p1 A1 u+ p- B( d2 y# H `//中间件1`/ f/ O1 j% t: s `koa.use(async (ctx, next) => {` 5 _8 s2 K+ g) B" b4 S `console.log(``"1 , 接收请求控制权"``);` - F- d9 h+ @2 \% _* g `await next();` `//将控制权传给下一个中间件` : O* Y* E4 S: T; g0 S `console.log(``"1 , 返回请求控制权"``);` 1 z) n$ q% n, @4 U `});` `//将中间件注册到koa的实例上` O: ]% y+ {) J1 r( q% H$ L& v% O `//中间件2`* C4 B1 t5 I3 A# y* T* e `koa.use(async (ctx, next) => {` ! _4 H3 ]) f4 w `console.log(``"2 , 接收请求控制权"``);` I8 j" Y1 w& G, g& B9 |: d6 K& v await next();` J/ a% Y5 |# y- e `console.log(``"2 , 返回请求控制权"``);` ) E, t3 A8 Y$ A& V9 W, D. t; ~( d `});` , @' h4 ^6 f7 `4 H `//中间件3` 7 t/ T" H- h) x9 d. @ `koa.use(async (ctx, next) => {`& A/ ^* P0 Y0 I$ R& Z7 D `console.log(``"3 , 接收请求控制权"``);` / o( A7 H( F4 B$ P" g' n. t. R `console.log(``"3 ,返回请求控制权"``);`$ ]) i4 v) e& X6 S1 F `});`- O& F3 n+ |# B/ O$ |3 f2 E: y5 B3 V `koa.listen(3000, ()=>{`$ y1 o( x, n6 ^ V0 M `console.log(``"开始监听3000端口"``);`; N& { f# d% g% X9 u2 @. ^ `});`
9 R$ R. B z3 y4 n0 l; I6 ?

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

1 K) N/ [5 Y- ?

访问localhost:3000的效果图;

/ E, V. {6 e f w- @
: i/ A& u' t, L/ }% l

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

1 Z* N1 U, ?/ X7 J

2.ctx参数的使用demo

& t+ H: q( D, x8 A: x7 P& ~8 E, L
`const Koa = require(``"koa"``);`- N" ^* D+ T- f9 ]- z6 M `const koa =` `new` `Koa();`: y |! d) _9 |2 O `koa.use(async (ctx, next)=>{`" U- c3 F1 e) _' S% ?6 b6 [ `ctx.body =` `"body可以返回数据,"``;`# [8 Y0 t6 u# h% p5 {. x Q9 O: B: X8 f `ctx.body +=` `"可以多次调用,"``;`9 q* N5 ^2 Y" S9 B W `ctx.body +=` `"不需要end()"``;`- t8 I0 ^# v+ x) N/ M) q `});` 3 Q* G+ Z( J% y, S1 Q/ }, J1 O2 X `koa.listen(3000, ()=>{`& O3 x# e4 l8 V `console.log(``"监听开始"``);`: W1 j+ Y8 s$ S& u `});`
/ |: c+ [( g, v) K, l9 k7 d; Q' H$ Z

效果:

- H c0 N6 n, P" {* ^* F! }7 V( d
" ]& G) p' S/ b/ K; P) u

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

5 J; k0 `6 i8 ~0 n- P n6 a8 d
`const Koa = require(``"koa"``);`) `# J8 C- [8 l `const koa =` `new` `Koa();` 8 b: R- a/ s8 W, L; M8 L; m `koa.use(async (ctx, next)=>{`0 V. b7 r" b, A6 K, t: ^ `ctx.body = ctx.url;` # y3 D" j+ l" V6 I `ctx.body = ctx.path;`( H! f/ _: L: S$ E) z, V `ctx.body = ctx.query;`* r3 _7 |) V: Q, v& e7 [$ a `ctx.body = ctx.querystring;`* B2 x3 O8 g8 k, E# u2 y `});`- h" S9 Z6 S+ Q& l: f; x5 ]; R `koa.listen(3000, ()=>{`7 z" Q* ?; Z0 q$ j4 r `console.log(``"监听开始"``);` ) T; J" E) m' @. j4 @5 p1 `5 w `});`
' i, i0 j* f( Z/ x& r

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

/ U T6 c3 N% l* a: L8 a3 ?4 S

1. url: 整个路径

! m3 z9 ~5 o2 K: U: z
( x" M* f! o0 D r* I1 `1 y: G

2. path: 非查询部分

* h7 M# Y) y' s8 b w
- q( [8 Y. Y9 q

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

" a5 G1 I2 `( q+ X6 W" s
! z# h2 Y. v+ ^& w4 b

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

8 U7 T8 |8 y. v P& i1 J
3 t; F2 V! L0 @0 ?( t5 {

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

2 [6 D; m, C" k- l

2.简单爬虫练习

6 k6 Q* A/ ~ B6 H6 C: [) z% X" y

安装request,cheerio模块

- [* [# d' ]' l7 b( g5 c1 ^: v
`npm i -S request: 请求模块` ; p$ w) ^5 D4 u$ ]9 z0 ? `npm i -S cheerio: 抓取页面模块(JQ核心)`
6 S7 X3 p, x) ]5 `

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

/ J/ s8 K* Z" o8 q( u& i ~
`//导入模块`9 n. E- M3 v9 |6 P3 e7 p `const request = require(``"superagent"``);` `//导入请求模块` 3 F' }' o: @6 E2 B+ Z9 d& S/ @0 O2 | `const cheerio = require(``"cheerio"``);`6 J* b8 U. |7 Q6 x9 [8 [ `const {join} = require(``"path"``);`" e7 o5 J1 `* Y `const fs = require(``"fs"``);`+ j& W# C& d6 [; t+ |. A% ~8 ~ `let arr = [],` `//存放数据` 0 P, X5 [5 q f2 a6 [5 A `reg = /\n|\s+/g,` `//replace中使用`. }& _' Q2 E7 _ C1 y1 P `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/)"``;`0 i/ g6 k5 x$ g% G; C `request`5 c3 Q# ~4 P* F* F1 C, }% z `.get(url)` 9 u, g3 a: S2 F% r `.end((err, res) => {` ' _7 i# ]+ m. q `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`2 T8 `2 k& g+ a/ y: p `$(``".course-item"``).each((i, v) => {`" u5 ~0 K( T4 j `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` , P& ?+ u" D9 H# Q2 }; i `const obj = {` . N# ?% h: N( K `imgSrc : $(v).find(``"img"``).prop(``"src"``),` ( `& t/ C1 r# I' {/ F- G f3 a `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`0 b9 B1 f2 o& F0 _3 g( G4 Q) A$ n `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` 4 w4 e Q8 E5 M6 H4 w `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))` 4 Q% m" L. i( ?8 b; }6 G& P& S `};`3 M" G/ V! V8 v$ U- Y0 B% C `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` ! ?4 p8 i8 N* \; L6 |: W/ f `arr.push(obj);` `//把对象放进数组里` 9 w( l2 B- |$ d' p `});`; W4 b# }' Q" s' e `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中` 4 x: K* ~' l B0 I4 Z5 b# k `});`
+ O* q# Z; e! e- w0 n D& n" b% W

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

& b/ f# w' q* [! _. Y# j: \: T- E+ ^ # s, U' `2 t4 o ! E, ^" t+ a$ Y& W2 f/ K/ r 6 y# j; d0 L* K _/ M/ D+ h) x5 d; ]6 |
回复

举报 使用道具

相关帖子

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