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

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

[复制链接]
$ I# S' T, i2 T' g. h

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

, ~+ O2 |4 k" [ w

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

! `) }4 h. U# B! V0 Q

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

* z! \' R1 g [+ V m/ J, G

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

W( Q& {9 |4 r4 V2 |3 ^ q7 a

1.koa

/ z8 f; L7 _! I1 f9 v) B

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

/ P2 m! f# P( w' t% J* Z$ N

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

实例化对象: const app = new koa;. Y- z' o: G& n2 F' i3 N% q

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

! ^: f- K/ y& d/ D9 a8 e+ z

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

+ `3 C! U" G& [/ [8 X6 M3 @" q

其中有两个参数:

5 x" o% [) X$ \. s S

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

3 [6 W; g- u. N0 h: W8 l$ l& y6 F

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

2 \& H. d9 U: Q8 r( K& _3 G* h# N( x% S" ~- p

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

# v( r- t( X) l+ L7 B6 b

1. next参数的使用demo

' l* P& e2 s3 Q( k8 _5 ?% V
`const Koa = require(``"koa"``);` 7 |, q g* |+ _7 w+ V7 d: r* R `const koa =` `new` `Koa();`8 Y5 G( `! ^! O t( r7 B; x `//中间件1` 6 ^0 k8 A9 o. s( d `koa.use(async (ctx, next) => {` . T) r* `8 u2 M' | `console.log(``"1 , 接收请求控制权"``);`0 m7 j' O; A+ Y; C$ E `await next();` `//将控制权传给下一个中间件`( ], s% k' o' E1 [/ Z `console.log(``"1 , 返回请求控制权"``);` 2 |5 J# q b* g7 b6 Y6 P `});` `//将中间件注册到koa的实例上`: `3 g+ g( P. n( B# X2 K `//中间件2` 9 m- H/ q* s; Q G0 j7 s0 K$ v `koa.use(async (ctx, next) => {` % O/ z* e( W- L `console.log(``"2 , 接收请求控制权"``);` ! `1 F* S& M; Y: F await next();`/ l2 U. S* Y0 |( n9 r `console.log(``"2 , 返回请求控制权"``);` ; X, P3 n& a7 L' [# Q! M( A, R `});`8 Q0 Z! H t2 [% P1 W `//中间件3` ' u: V; b$ O4 b- U4 ^ `koa.use(async (ctx, next) => {`( h- z+ j* o; B/ p* l `console.log(``"3 , 接收请求控制权"``);`( J3 A* e a! i/ U `console.log(``"3 ,返回请求控制权"``);` " Y" B' o8 @/ Q9 ? l6 x `});` & \+ X9 L, p+ ~6 E; ]- i) i `koa.listen(3000, ()=>{` $ y0 c- Q, L/ N( V, ]% C `console.log(``"开始监听3000端口"``);` % ]4 O0 x2 r6 ^) j8 k, ^ `});`
0 p0 u$ W) d: ?: U, @! d6 a

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

& P! [ s( T. z7 s; U1 A) m

访问localhost:3000的效果图;

* y! _, G+ U. s* M; v* A- ~! U/ \( n
, U6 O! @2 _1 I& a" Q) z2 S

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

& _- ]8 G* w: d

2.ctx参数的使用demo

5 W' T; d8 V3 T8 V' m1 e
`const Koa = require(``"koa"``);` ) i5 Z5 _* d* \' T `const koa =` `new` `Koa();`3 b7 b5 {2 a N- r& j `koa.use(async (ctx, next)=>{`8 s( j# b: G' G) I `ctx.body =` `"body可以返回数据,"``;`( Y4 u) Y2 l7 T9 }( x/ l: H/ l$ \- ` `ctx.body +=` `"可以多次调用,"``;`$ R# a& N0 B, n7 Y; m9 ^7 K8 C `ctx.body +=` `"不需要end()"``;` & f8 M; k: {% J$ ~" g* u7 Y `});` U* Z1 e3 x8 ?9 V" D) A `koa.listen(3000, ()=>{` , O" t8 i7 v8 O/ j& }' z0 a7 _ `console.log(``"监听开始"``);`9 h W, J2 R! y+ E `});`
% X* @, K% @: P2 W! H0 E

效果:

5 [) D' E4 @: B& p h3 @
3 s1 ?8 Q- D/ o1 q2 F

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

1 J. G! y% G3 Q
`const Koa = require(``"koa"``);` 9 @; S: A- I i n* r) y' h `const koa =` `new` `Koa();` ! s( p0 e$ y' [8 l" @2 |# f `koa.use(async (ctx, next)=>{` 2 |; |- x! g0 }& O/ i& g, U `ctx.body = ctx.url;`2 m. T, j$ I8 e: X* u `ctx.body = ctx.path;` $ M9 e4 i1 Z9 W- u9 B `ctx.body = ctx.query;`! d! X }& a" U- t `ctx.body = ctx.querystring;` : h* H' i4 m) b f; K `});`) H* X% u# I2 I% X9 Q `koa.listen(3000, ()=>{`7 B4 u7 X% Q- k5 V$ }' V4 d `console.log(``"监听开始"``);`( P0 A' K( E4 Q5 E `});`
8 D( g0 i4 C1 m3 R4 y8 U

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

- P! S0 Q1 J. g/ Z% \ G+ M

1. url: 整个路径

. w# _& R7 g) a9 v( e, z" K8 p+ j
C7 m) B5 I8 K8 k

2. path: 非查询部分

1 @9 u0 z! n! r7 s1 s1 c
+ T9 X, a' z; G$ w; {0 x7 U! n1 \" d

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

1 f% n. c- }* M0 I5 ~
8 ~6 A1 C$ b% K+ h: L

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

9 S! s b2 R* d) m8 o! T5 E
1 z* M+ v% B P& L0 T+ Z

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

7 Y( y% Y( k/ I

2.简单爬虫练习

' g8 w- L4 W* c2 ~, y

安装request,cheerio模块

X N+ y/ Y; V& p3 U; |) y
`npm i -S request: 请求模块`! t$ |" `. E& ~/ S% {1 c `npm i -S cheerio: 抓取页面模块(JQ核心)`
: H& _( m5 c \/ t# w h1 |0 ^

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

3 b$ I2 S: M& j6 m: R3 d# U4 m
`//导入模块` D8 k: x& E2 J3 L' Y `const request = require(``"superagent"``);` `//导入请求模块`0 m8 i0 D! d% Q5 @ `const cheerio = require(``"cheerio"``);` . J& C9 ^* i& d, k% S- c% z2 u( n `const {join} = require(``"path"``);`9 x- r4 y, t* J# A. C# Z `const fs = require(``"fs"``);`: G! U. u7 `9 l+ ]4 B6 k# | `let arr = [],` `//存放数据`0 J6 ]; A9 e* K. Z* s8 X `reg = /\n|\s+/g,` `//replace中使用`$ e O, r H% @( H: C `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/)"``;` 3 S& x$ }6 s5 x `request`, f4 p: |+ E& o3 E `.get(url)`- z2 s; e$ Z5 s$ N) ]6 s6 v2 x `.end((err, res) => {`8 q) |3 Y" q4 e0 l* i7 a `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用` # n0 ]# L! U: ^0 i2 U' h' C$ y$ { `$(``".course-item"``).each((i, v) => {` ; K8 A' x( i v/ v& W `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`1 p+ ^" r* r' C. X1 m; a6 ]. f `const obj = {`* b" F2 r& [) b! m) M `imgSrc : $(v).find(``"img"``).prop(``"src"``),` ; x$ I" l( [$ U- J- e- A8 Z `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`: z6 Y3 [; m, c/ Y `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` 1 @5 R. I8 ~& s1 X: a& }. A' v$ M4 w `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))` $ f. c% ~" z V% C0 e o& U `};`$ j2 F: G+ e9 v W! e3 ] `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` 7 r% [( H2 \2 |( n `arr.push(obj);` `//把对象放进数组里`1 x+ h" b H# S/ q$ I/ ^* v `});` 6 W+ @" ?% P- e, M! E0 u. o `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`, C, N( C( _7 u) p/ { `});`
9 q. H* }4 Y! j

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

' @" ~# {1 }7 g5 n% J 8 Y, ?7 J0 C7 G& S P * Z- a) f' }, S, M" [ / b S4 k0 x& K/ B 2 d" _( d2 x7 _- P% h7 S; m8 }; {3 M
回复

举报 使用道具

相关帖子

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