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

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

[复制链接]
3 |4 ?* v% k; z2 w# B+ i

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

- \2 A: Y# |3 C! X& k& m2 L; ^( ]

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

?* A: l5 V+ A! _

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

8 B! R) {, ^. Z' y

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

, e+ O% O& P* A N4 Y0 K

1.koa

d/ H* T& w& h1 J

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

- ~) h& t2 l# u0 X% F+ u8 D

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

实例化对象: const app = new koa; ; s, N' \3 K6 O0 N+ ?% @

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

5 g0 y$ p8 t+ \2 q" E

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

5 q8 o& x6 E2 r$ L+ W1 o

其中有两个参数:

/ W+ L) Y6 B$ D! _

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

" N x: V% J6 I# ?% @

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

! @# b* m8 D+ }

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

$ D6 j5 u' d( F t) N

1. next参数的使用demo

4 C. @3 a" d$ k4 ]! R& R
`const Koa = require(``"koa"``);` ( B) J, ^# s- @ `const koa =` `new` `Koa();` ' ?9 r6 f V! L) ^' v `//中间件1` g- t# H5 x5 I- U7 ^ `koa.use(async (ctx, next) => {`! b2 c* A% o' D4 n! o0 ` `console.log(``"1 , 接收请求控制权"``);` 1 ]4 Q% P7 \; s" ]8 ?9 _' @- g `await next();` `//将控制权传给下一个中间件` " n [8 d6 s7 s3 R `console.log(``"1 , 返回请求控制权"``);`# T8 |4 _; l* s x, \ `});` `//将中间件注册到koa的实例上`' ~$ F5 j+ B# z3 b+ X `//中间件2`/ d2 v- n$ I# \4 b4 a- S `koa.use(async (ctx, next) => {` ; P \1 x2 W$ c- H' N- F `console.log(``"2 , 接收请求控制权"``);` ; }9 t b( U) V! P: A await next();` & G( Z# M5 X* M# Z0 v/ A `console.log(``"2 , 返回请求控制权"``);` . c* A2 A9 b, b+ |6 v& |3 H `});`' ]3 `2 F. O% X9 D `//中间件3` % g8 [ l7 u! U `koa.use(async (ctx, next) => {`0 w6 | C. h m2 j2 z `console.log(``"3 , 接收请求控制权"``);` ( G. N. x5 k2 _2 G `console.log(``"3 ,返回请求控制权"``);` 4 n$ Y/ E4 h0 B/ t- E3 T2 x `});`. o/ V& {! V- B! T0 a$ X, P0 l& h `koa.listen(3000, ()=>{`! a1 X& K* k+ w, L& p `console.log(``"开始监听3000端口"``);`/ g- N; z3 b$ X) e `});`
) P& I. T& C, n' J

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

$ e8 f5 z3 {( g

访问localhost:3000的效果图;

8 r7 Z" i1 e5 E- C/ D
/ j o( |- e$ e9 d

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

& G( q' W; n& U9 x/ |' Z7 c5 ^

2.ctx参数的使用demo

9 g! X B& O( v
`const Koa = require(``"koa"``);`) f/ m9 U" e6 D$ X `const koa =` `new` `Koa();` 4 ? }( V, O. e+ P% s% F `koa.use(async (ctx, next)=>{`) @1 d1 l6 b- g3 X7 _/ B: W! j `ctx.body =` `"body可以返回数据,"``;` 9 K4 n3 n4 o% |+ L% A `ctx.body +=` `"可以多次调用,"``;` U% i# F: Z* H" h% {7 Z `ctx.body +=` `"不需要end()"``;` / `$ b9 ` ^. P8 Y* m `});`* T( v0 `* v, g5 z: D |9 A `koa.listen(3000, ()=>{`9 ~; O/ W: S# E/ T `console.log(``"监听开始"``);`" K7 X# F0 V5 u# ]9 m! k `});`
- t( A6 C2 r b; \$ f8 `: K. t

效果:

2 G% O" c6 Y1 F9 z+ C3 ` U, k
* S. f6 k8 a1 m0 \( a# X' O& V+ z

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

7 G. Y' e5 z. M' E/ K
`const Koa = require(``"koa"``);`+ n+ s5 Z+ ~! R& n1 Z+ j0 m5 W `const koa =` `new` `Koa();`9 D& v0 ]- ^: G& m' C( w' f! D `koa.use(async (ctx, next)=>{` % E) R% y$ U- k& g" J `ctx.body = ctx.url;` ' t& D) {# { n% ~0 l9 z) t2 k _ `ctx.body = ctx.path;` 1 l3 D; {' z8 N; W; C `ctx.body = ctx.query;`: w' n, m& P' b7 D* j3 @ `ctx.body = ctx.querystring;` 3 x; b' ^6 w5 s+ A! p/ F, Z `});`2 `. E1 b8 f/ Z/ R3 j& p `koa.listen(3000, ()=>{`$ B0 |* a5 x& f2 y, x$ d `console.log(``"监听开始"``);` 8 a5 |/ f6 \5 t; I, g+ j `});`
U5 q4 d$ P" K( n) Q7 n

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

0 c% [. ~; j, m$ E7 s

1. url: 整个路径

' f3 U# _% _; ]* ]3 _' p& n7 R
& L4 s' n" Y+ S+ i; i" ?, A" E

2. path: 非查询部分

{% ?; d$ x% k9 _( N0 e
% U- w5 h$ y7 B( _: P. O

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

, z8 d' b7 B9 S* b1 @
! ~" v5 m. i7 H4 L- z

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

% u: ]( z a+ V7 f; v
. J) p% N! d h* X

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

3 e# f$ w2 J1 K- ^& n: s

2.简单爬虫练习

8 B( C) ~1 ~& M" k8 |0 [/ ?

安装request,cheerio模块

7 W7 u8 e# \+ n
`npm i -S request: 请求模块` 4 S4 ]& O/ B2 |$ G$ h9 q& A: x N# j `npm i -S cheerio: 抓取页面模块(JQ核心)`
5 x" U8 ?) b( E2 p5 A% Q% W7 e

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

4 _3 h7 r' `. L/ U$ O L- j: i. t
`//导入模块`2 d" H/ }4 R( i7 C! ]& C3 e& c `const request = require(``"superagent"``);` `//导入请求模块` 4 r/ t: N. B0 X4 k `const cheerio = require(``"cheerio"``);`! Z1 C1 K. s$ l$ n9 F `const {join} = require(``"path"``);` ! `- o, e. m; ? `const fs = require(``"fs"``);`1 k: m8 n9 d9 _2 z5 F3 j: c8 C `let arr = [],` `//存放数据` * X( p% E4 H$ U9 Z% q8 V9 }' r `reg = /\n|\s+/g,` `//replace中使用`1 [/ |1 X2 s9 R: d" E* a `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/)"``;` u2 ?. T' c8 w( T `request`+ N. P, |4 p# }6 }" W% D, U$ c: u `.get(url)`4 ? [ Z- Z0 P% ^: l+ `. A. ^ `.end((err, res) => {` Z! F6 X( A" a; ?9 A- R `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`9 z d0 i3 Z* _ K `$(``".course-item"``).each((i, v) => {` ' R( @8 g7 B3 [" q `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` ( _2 `0 F: s) {, H9 L) N7 A5 z: r `const obj = {` ; y$ z( _: \' Q$ a" y `imgSrc : $(v).find(``"img"``).prop(``"src"``),` ! H! O3 ]7 Y3 K$ u$ k `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`( O' R7 |" ]+ `3 k4 A; c- ^ `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`9 {8 F' C8 l* L `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`: b! {( f/ y. W% B) F# ]4 b `};` % t r5 b# f7 k `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` ' M6 u) x8 m1 ~0 f' U. @5 _ `arr.push(obj);` `//把对象放进数组里`5 w8 a/ j! }# ]- Y3 w: o. K `});`$ S. f3 G1 e& |$ F# ? `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中` * b3 ~, q7 Z& ?# c( ]6 ~+ u' | `});`
) `6 J g5 v$ L5 e; K

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

5 Y, I" b: }2 y. C$ g 2 G! J2 d, Z( V3 O " y& A5 L- _; k% {. L, l* q/ K' ~- V- v8 f, X/ C 7 [# j: k: O/ l& q6 j6 }
回复

举报 使用道具

相关帖子

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