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

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

[复制链接]
# J, b8 T4 r3 C: T4 S

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

4 L2 H2 y+ {9 U+ c% f S+ j4 }8 O

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

X6 x5 l" W' ?3 w0 {

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

$ ]# Q Q" g1 A7 @( |, K

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

7 U. x& a' E* P0 f9 ~

1.koa

0 |0 m# {; U6 n( k

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

1 {+ Q# x! @8 W

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

实例化对象: const app = new koa; - s. n9 L" R4 p3 a

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

4 ]1 ?. a4 U0 u7 V! G5 l

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

, Y, _4 f7 I; m& B

其中有两个参数:

4 i5 E3 d3 d# ~! V9 y5 A

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

" m% u! E- l+ Y7 J# n6 g: v- a

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

6 \: Q* U( |+ p

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

# N1 T* R0 ?$ d4 b

1. next参数的使用demo

# ~8 q' M& c$ G# y! Z
`const Koa = require(``"koa"``);` 0 b$ o: Q5 R7 ], u- ?: v) j `const koa =` `new` `Koa();` . L V0 O( j0 q/ ~ k9 P `//中间件1`0 [, u" B j: x+ x' y0 C6 R/ |. X `koa.use(async (ctx, next) => {` 9 t2 Z8 h$ J* q* o `console.log(``"1 , 接收请求控制权"``);` / L. ~6 P, D& a$ v `await next();` `//将控制权传给下一个中间件` 3 {/ \% e9 e$ e) [$ f& y& T `console.log(``"1 , 返回请求控制权"``);`0 u" r8 O; l; _* L `});` `//将中间件注册到koa的实例上`2 M. q# |# b6 L* @; u2 F) V X/ D `//中间件2`, N( O* _2 S$ l. f: P `koa.use(async (ctx, next) => {`0 B4 [9 e( l) R) } `console.log(``"2 , 接收请求控制权"``);`; J' _) s$ h0 |! J4 Z6 h. T# L( ` await next();`, ~" M) E# \4 }7 O, m2 L; j `console.log(``"2 , 返回请求控制权"``);` / G0 B* n. L# a' N1 r `});`5 K, t+ k( N Q6 p5 ]3 g4 ?) G* H `//中间件3`! Y; F5 ?) C; ?3 @ `koa.use(async (ctx, next) => {` 7 r6 R: U2 L: b0 _0 Q `console.log(``"3 , 接收请求控制权"``);`, A8 D0 D ], F* N5 b `console.log(``"3 ,返回请求控制权"``);`- h4 }) N/ h5 m5 d `});`! T: Y$ Q7 q2 ~1 \# l `koa.listen(3000, ()=>{`9 y; A# h- V0 }* | `console.log(``"开始监听3000端口"``);` 6 j4 q: {9 O; q `});`
! M# |8 U* E( x5 k R2 Y# }% H, J0 W

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

' Z3 f* h: ^( t2 D- v

访问localhost:3000的效果图;

4 Z5 X: e( n n* Y) _ e, Z! G
( L4 c; c/ d' u) ]

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

5 b6 `$ u7 N- s: V! _$ P

2.ctx参数的使用demo

7 U' M/ ~8 q( a# @' t
`const Koa = require(``"koa"``);`. R. u2 K) B# \; l+ D0 s' @ `const koa =` `new` `Koa();`5 B0 v3 Z d- r% }, E8 j `koa.use(async (ctx, next)=>{`. K9 R: V( j# ]# j5 L0 g) ] `ctx.body =` `"body可以返回数据,"``;` w% N$ m- x+ O5 @+ o8 |& Q `ctx.body +=` `"可以多次调用,"``;` a2 d! i8 a2 {7 y- w6 \ `ctx.body +=` `"不需要end()"``;` e1 [1 J* m1 _. |( m+ b4 |5 l" b+ k: N `});` # F6 [ X/ ~ L/ _3 S `koa.listen(3000, ()=>{`1 L, B' U& a0 {) r- @1 W `console.log(``"监听开始"``);`- N- V6 Y6 z6 N: k `});`
# B. M" V* K4 l0 v t- L7 f+ `- \

效果:

! P: p8 d, [ b! _ r" b" F0 W
* L# B- L) Y/ ?4 f: t7 N3 D; m8 q* R

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

7 b" J( M$ U( V* P
`const Koa = require(``"koa"``);`. w3 g, n8 m- P" `' ] `const koa =` `new` `Koa();` $ C& [7 w8 l4 x8 [, U1 G+ s, d `koa.use(async (ctx, next)=>{`$ y2 c; O+ |( K7 l3 v+ w0 s! p `ctx.body = ctx.url;` . W2 c- Z# s1 S- v `ctx.body = ctx.path;` : x$ `' o. W! `; r/ n$ S% n" E: t `ctx.body = ctx.query;` . u- _. ^6 u5 ~ `ctx.body = ctx.querystring;` : l- ~( c( S) A" z `});` : s" g0 I5 @+ [2 C `koa.listen(3000, ()=>{` , G- g4 j* _$ F0 `. `2 X7 r `console.log(``"监听开始"``);`- y/ H! y: V' o, [, z0 f! P+ H4 P `});`
# h5 O- s5 M& ?+ [+ N4 d0 r

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

- ^, M5 m% `7 f6 X" l

1. url: 整个路径

+ g6 f5 ^/ r7 u2 a; N' x1 r& M
/ R" m, ~6 c) h2 F/ g x

2. path: 非查询部分

# k3 L: \9 w% a
' H6 j t! G) v$ X5 |- @) _' |

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

( c6 X0 {4 a2 N- c
- t3 U4 s$ P: W7 X" d5 K

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

] S7 i# H8 d2 b4 p
" W. q' Y( H8 i

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

- c, [, _, g8 Z% f- o3 i. Y

2.简单爬虫练习

3 }6 h _- `8 Q

安装request,cheerio模块

4 q$ {6 V* C: Y1 p
`npm i -S request: 请求模块` ) @- u( W, ` m: w1 l z `npm i -S cheerio: 抓取页面模块(JQ核心)`
6 C* {' l# d. {- |9 U/ b: u' Q

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

" d/ R3 P4 D5 z3 r2 X- }
`//导入模块`; A4 C7 r4 Q R0 x, R7 E7 r/ X `const request = require(``"superagent"``);` `//导入请求模块` ' D! {1 L( ~$ N; ~: }" D7 ~! [% s `const cheerio = require(``"cheerio"``);` 1 G* a U1 ?' U/ ?; P# t. y3 B `const {join} = require(``"path"``);` : F( B" r# O: R" l" h% S `const fs = require(``"fs"``);`/ ?# W. [9 N# i6 D0 K& Y* c7 \5 m `let arr = [],` `//存放数据` ]0 r- i( z$ b9 _- m. ]. X `reg = /\n|\s+/g,` `//replace中使用`3 k' q3 q/ E( Z/ \- ` `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 z5 }; x9 o! O( \# x' M T3 i1 _ `request`: O) t. k7 p3 k' ^! M `.get(url)`4 C! }- L! |8 M `.end((err, res) => {` ; w0 x1 F! q: f9 \ ^6 _ `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用` k+ d, b! n! R; m2 E9 C `$(``".course-item"``).each((i, v) => {`3 M6 P1 U$ A. m2 t `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`8 m, |5 d4 `( L3 o0 h8 P' l `const obj = {` / n* `6 x8 D- ?8 A6 u! _ `imgSrc : $(v).find(``"img"``).prop(``"src"``),`( x( X$ p- V) j4 _* n F `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),` & K) e% X0 x. N8 m `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`1 P( N0 V; k( l$ o' ?. Z `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))` 3 p5 e4 E+ G" A7 w% k `};`# B; U' `* i# }+ w0 j S+ U- ~ `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`2 x1 U5 t( C" ]" {1 [$ i s2 M `arr.push(obj);` `//把对象放进数组里` ; y6 {* v' J: D4 M- G: e2 ^ `});` ; u% z8 J' P' @/ |! Y5 c `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中` " v+ x. a, `* b1 f# A- C* c `});`
! M* Q) [6 T- D! a4 {0 x

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

% o' P# a- f0 T2 D* W 3 V( w1 o" K' p$ _- [ ( {6 Z; X( {! o. B$ Q# {& T1 a1 D. B# E( v ; j5 P: i0 L- K% `$ R' y
回复

举报 使用道具

相关帖子

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