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

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

[复制链接]
1 [( `( K" V S: K

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

0 m. a. Z: |4 X) ~( ]

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

; P+ c. O8 a: q. e/ {3 A

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

) {% Y- J: o2 z+ C& R: H1 v

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

, h( F' I1 o# V/ m, I

1.koa

4 O# y+ i8 ]/ v: z6 Z0 A# Z

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

9 k% O D8 i) x6 n0 s

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

实例化对象: const app = new koa;0 O+ r C: e$ H. \2 Q

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

" E; J9 k! w( e1 m" E

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

- A4 Y! v9 G; Q/ X/ V3 q

其中有两个参数:

) e1 s M2 q2 G

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

/ M$ t* e" P- j4 c6 S% {- H; o

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

6 \) U) c, U+ M! }3 h' g+ J. @( |% t

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

$ [' y: i7 l8 n1 F9 o

1. next参数的使用demo

+ W+ b u" A. P$ a4 }$ Y
`const Koa = require(``"koa"``);` 8 x" K4 P6 C$ e6 F `const koa =` `new` `Koa();`7 |/ f% E$ g: ]3 u z* ^5 L `//中间件1`. W9 N3 I, [1 J& {8 P/ W% u, h `koa.use(async (ctx, next) => {` ) U) m. ^) b/ b% O `console.log(``"1 , 接收请求控制权"``);`3 X9 A& D; }. Q' ^. T `await next();` `//将控制权传给下一个中间件` ~3 ~ w& V. B% U, Q `console.log(``"1 , 返回请求控制权"``);`5 [' K9 q6 F' @! }; c" l1 R- x `});` `//将中间件注册到koa的实例上` / q' @5 A# @" x0 P$ c4 ^ `//中间件2` . }/ _& d, L1 v `koa.use(async (ctx, next) => {`8 R; F b: F' i. G+ N `console.log(``"2 , 接收请求控制权"``);`4 }4 b3 T4 V1 s6 |# W) @$ [ await next();` / I2 x0 X, [& \1 d, n" B! }2 ` `console.log(``"2 , 返回请求控制权"``);` 4 D* Z$ X% z+ n9 v+ P) c+ g `});` 3 @1 F j. v% M2 P3 P; }7 B `//中间件3` , y$ D. O7 l# p `koa.use(async (ctx, next) => {` 1 @1 \% e3 _2 }2 S+ E; ? `console.log(``"3 , 接收请求控制权"``);` . y5 G! y& c& F6 i `console.log(``"3 ,返回请求控制权"``);` ! P; ` ]8 X: ?. z4 U. Z- @. T `});` 8 r* h4 W; P/ f# x6 T9 Z `koa.listen(3000, ()=>{`& ^# M" q u/ M6 p' f& Z6 M `console.log(``"开始监听3000端口"``);`9 q. V3 C8 z( r# t1 r `});`
L( z7 C2 }3 H+ Z0 ^+ {0 v

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

6 A% C$ w9 @+ J( k$ a6 F2 Y

访问localhost:3000的效果图;

% a% X5 [+ I; p' R. V
$ H. @) B5 \/ @9 \

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

3 _' N, o/ V5 y

2.ctx参数的使用demo

* l2 N, G+ S' s- t7 v* k! u
`const Koa = require(``"koa"``);`3 g2 C1 d O, Q q- X7 x2 b `const koa =` `new` `Koa();` , }6 v- g3 b$ |' x+ f3 \ `koa.use(async (ctx, next)=>{` . g! y4 Z9 C: G& s' w/ u `ctx.body =` `"body可以返回数据,"``;` & r2 t$ j' o* Q; d+ X5 t `ctx.body +=` `"可以多次调用,"``;` , T3 r. `8 V9 ?; v; h8 x `ctx.body +=` `"不需要end()"``;`+ C( q( @0 Z. M" `3 R `});` , r# S) q G( s( r9 f `koa.listen(3000, ()=>{` $ S9 L+ Y9 v* U* w7 Y( ? `console.log(``"监听开始"``);`( g( g$ Z9 e$ Y' V `});`
; K8 O! X4 j) n( b2 W7 U) k

效果:

, z1 N' Q( v: g8 H; }/ y8 T
' a- m8 ]5 d- T) l" z4 L

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

! G9 G) [( N2 k
`const Koa = require(``"koa"``);`9 J' Q" O" w4 F0 V3 A! a( D `const koa =` `new` `Koa();` & D5 D+ P: L3 P! I/ V7 R" d `koa.use(async (ctx, next)=>{` ( m V" |( h& ^- h8 n K- b9 w* `; ^ `ctx.body = ctx.url;`$ f8 m! S* j$ _% j1 m `ctx.body = ctx.path;` ( z) r" k& U4 b# J' ^2 r( e `ctx.body = ctx.query;`6 e; \3 `. j# Z, x `ctx.body = ctx.querystring;`( l9 b& y2 D5 J1 ]" V* @ `});` / t2 T; D6 P# b* Y/ y* \9 p5 A `koa.listen(3000, ()=>{` ( e- \# R! s& L( Z/ j$ C `console.log(``"监听开始"``);` . G6 }) y2 N3 V. P; ~ `});`
3 A- F6 z8 N, b( O& C

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

. q$ m' X) Z4 T; `2 W

1. url: 整个路径

$ f; w. |' x. ?8 ^1 z8 Z1 W
% I& O: q6 K, |

2. path: 非查询部分

5 f2 g! J2 s: ?6 A! I
9 K. w# K ~8 z0 ^& Y

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

8 e; O+ `9 V3 A! j9 b
( Q8 D! p8 o3 u; o. `8 N

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

/ E- g& t3 t& [" v o4 j
5 y3 f" D# o9 f4 e/ f

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

: i; h/ t3 ~$ V* \

2.简单爬虫练习

# V3 N0 Q/ K/ v0 }9 T, W( p* r

安装request,cheerio模块

# a% `* a3 }2 ]: \7 z
`npm i -S request: 请求模块` $ l' }/ s; }! l2 N4 @ `npm i -S cheerio: 抓取页面模块(JQ核心)`
2 \ ]) y; K0 e9 R; s

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

+ |$ l" A3 A: X( x8 _/ R g
`//导入模块`( t6 P6 m. K4 _2 x. ? `const request = require(``"superagent"``);` `//导入请求模块` $ b6 E2 x, s- y0 P; v `const cheerio = require(``"cheerio"``);`7 _% U7 |$ v! `. _ `const {join} = require(``"path"``);`0 {& \4 C) l7 ?( ]9 ~5 N+ v `const fs = require(``"fs"``);`( O' u' i+ n8 F `let arr = [],` `//存放数据` 9 t7 M8 i4 D( l: e `reg = /\n|\s+/g,` `//replace中使用` 4 U' y8 x! H/ U* E) h! w$ R3 e `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 M! O: Q" E5 Y; M. k" f4 v- D `request`7 v2 ]+ g# G$ G6 O% I( _; S$ s0 ~ `.get(url)` 0 M9 u( p: ^3 ]# g/ P% D `.end((err, res) => {` 1 H4 `* v. _/ g! |% ^4 B: Z `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`$ J+ u) Q6 Q9 _% S5 o" H' r6 b3 X1 ` `$(``".course-item"``).each((i, v) => {` e" U9 D$ g5 W* d8 C+ B `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` + d7 f& P1 R# G9 @ `const obj = {` f4 ]9 p+ z$ P; p) ~ `imgSrc : $(v).find(``"img"``).prop(``"src"``),` " V7 w) N) N1 z `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),` 9 F ?" X8 n6 n- B$ j5 M7 ^ `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` ! d* x7 D) j& X: y* ^- |2 x/ \ `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))` + E. g# z+ ~# {- f5 ^ ?% e `};` * T# u7 j: v1 {+ e8 q0 g3 a `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` u2 q- U5 t8 h3 b9 S5 q `arr.push(obj);` `//把对象放进数组里`0 S# W$ g/ L5 k1 b# F( X g `});` - m o7 {' x4 h+ f `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中` : k$ f' n6 K1 a3 O `});`
8 j; P, s) o! e+ f/ i

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

5 ^; ]# z; V: a& g 7 W7 Y" ]: Q: X$ R 6 b! z+ c) M; T+ t1 b* s0 G % g/ ^: F( H, @9 K1 f 5 N/ q1 P3 C6 i1 a# z9 h. I* Y0 V2 z
回复

举报 使用道具

相关帖子

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