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

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

[复制链接]
% l7 F+ r! ]3 q0 X* B4 E

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

, @5 h0 y6 E% L+ k

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

4 [$ W% v* W1 ~ ~( c6 g

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

/ D9 q- H N) C1 c, a. h

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

" _# Z/ r- B; b# s2 F1 G) s

1.koa

- m' Z5 b8 }1 Z* l

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

/ f$ i) f2 {; X; w8 g

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

实例化对象: const app = new koa; ! F4 `9 m5 `* E

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

4 h3 c, M- K: T, c

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

7 Z4 |3 t" F& Q' X6 S

其中有两个参数:

+ q1 u: k1 W1 t0 g

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

- ^4 C, f G9 o# D1 d; d& l

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

$ t7 y! g9 }/ Q

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

9 ]! x2 v% U$ v3 M. d

1. next参数的使用demo

9 l) ?# E* \8 d% Q3 ~; o
`const Koa = require(``"koa"``);` $ W. N, W! _1 C7 F+ }+ ? `const koa =` `new` `Koa();`$ K9 |" C" d$ ~+ J4 n `//中间件1` / ^. N$ {% f( k9 b5 i `koa.use(async (ctx, next) => {` & E l u P# C( z/ ~ `console.log(``"1 , 接收请求控制权"``);` # u2 s; [$ }7 l2 k `await next();` `//将控制权传给下一个中间件`9 k/ H" L1 P5 ^# S, D& J" Q `console.log(``"1 , 返回请求控制权"``);` 3 o! u: C! W ^* r0 k `});` `//将中间件注册到koa的实例上` / q: s/ }/ d% W7 v2 I+ N1 u `//中间件2`3 W- m/ r/ d Z u. ^) v3 v) _ `koa.use(async (ctx, next) => {` 4 Z, {$ J! W7 w. e& R `console.log(``"2 , 接收请求控制权"``);` & V! v6 X% J# G5 V await next();` , A- x2 f4 w+ K( R& K6 X `console.log(``"2 , 返回请求控制权"``);` & `/ b) l- Z g `});`, B# _; G2 {: g3 V `//中间件3` / p( }8 E7 | V `koa.use(async (ctx, next) => {` 0 `- ?# c* h8 } `console.log(``"3 , 接收请求控制权"``);`" D% S1 ~1 E9 c# {0 ?& g' O; D `console.log(``"3 ,返回请求控制权"``);`' r% e' m# w) ~3 i- w `});` ( T5 B0 W: }" \2 U) N; D3 I- | `koa.listen(3000, ()=>{`- b8 C; r' x0 A& f9 ]1 k `console.log(``"开始监听3000端口"``);` ' H- t* W6 n* X( X6 \9 \ `});`
8 b, {# U/ d" v' h$ l

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

. y/ s7 g7 T, B1 z0 _: j

访问localhost:3000的效果图;

7 c- j9 L6 o9 @# a9 g+ F
0 e3 z9 Y6 E6 z X

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

' O! V: V2 C3 J. m) |1 |

2.ctx参数的使用demo

' B9 m% m2 {2 w8 m' x, O: k. \" T! w
`const Koa = require(``"koa"``);`6 x8 K, n& B* S8 B# ?1 x0 z `const koa =` `new` `Koa();`) j: Q5 u! c6 B' Y+ {6 t r `koa.use(async (ctx, next)=>{` U+ L& s# e9 \; B" T$ a `ctx.body =` `"body可以返回数据,"``;`/ q# {% A' B/ v1 A" c: j% J1 ]& `9 } `ctx.body +=` `"可以多次调用,"``;` 6 x$ z$ a% y1 F: _ `ctx.body +=` `"不需要end()"``;`, Y5 D+ U% ]+ o: P3 ^# _ `});` " g( |. i% w [1 t `koa.listen(3000, ()=>{`$ |. {+ L6 P. y: Q e! p3 D `console.log(``"监听开始"``);` ' C& H; Q; m. M4 U `});`
M" A% B9 L" T8 c- g! C! P

效果:

3 O6 E7 g& i% G8 p
- U& D+ F5 C8 R# u/ k6 R

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

5 _9 x9 G; E2 J, q* x9 s! B% L
`const Koa = require(``"koa"``);`! @0 j# a: a# Z h9 C `const koa =` `new` `Koa();` 3 ^( U3 b- e# L" a1 c `koa.use(async (ctx, next)=>{` + S8 u) d/ |* b8 S9 n# I `ctx.body = ctx.url;`) K- j4 D/ j2 Q2 w `ctx.body = ctx.path;`9 f/ h3 x w+ N2 k* j y9 ^ `ctx.body = ctx.query;` " z l7 h4 E# L6 A `ctx.body = ctx.querystring;` # a7 X1 B% m5 i" F6 w# _! p `});` # Z7 v, c5 J& R `koa.listen(3000, ()=>{` * a' ?+ Q$ ^+ b& `- N4 H `console.log(``"监听开始"``);` 4 Y0 q: A, M) n. E) @0 @2 n, Z `});`
4 m; \! ]: a# [3 I

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

^4 X( T2 S$ [+ {% p" ^6 L

1. url: 整个路径

+ c: @( v7 p0 ]& b e: C0 c. T0 Y) G( s
4 e- I% I4 f- q1 I( B

2. path: 非查询部分

- |. Z% U) |$ t: k5 z) [
( U- E8 j" u* f

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

* }! Q! d6 I1 [6 ^
0 Z/ T9 S8 R* L

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

# l, Q2 O+ R* r$ i3 Y
2 j+ B, k6 J( ~( X- R4 N" G

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

8 ^$ p1 n/ c1 M j* c

2.简单爬虫练习

8 V9 Y V% i) j) z2 { w5 p

安装request,cheerio模块

4 k, K5 n# L0 w1 I; ?0 m( N( L/ g% r
`npm i -S request: 请求模块` 5 I0 G& F3 ]7 y0 e. h+ T- W `npm i -S cheerio: 抓取页面模块(JQ核心)`
( U" a9 z. C! [ H/ r# |1 ^

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

7 }/ o5 W$ K \0 U3 K5 _2 U$ L
`//导入模块` 8 r1 H& P8 G$ @/ h8 e `const request = require(``"superagent"``);` `//导入请求模块` ' a! f8 Z9 Y" T f9 [" p0 E% @ `const cheerio = require(``"cheerio"``);`, c1 S1 M) V! z `const {join} = require(``"path"``);`2 b4 V; O! Z/ `7 i, u! L `const fs = require(``"fs"``);` b8 l+ B0 ]5 f) l$ ?5 I `let arr = [],` `//存放数据` , x9 i' B3 g# J1 i `reg = /\n|\s+/g,` `//replace中使用` # ~% ?, \; p+ C0 A, |7 M `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/)"``;` 6 ?1 ]0 f& [( K0 d `request`1 b4 j* B0 Y9 C6 Y' z `.get(url)`3 W0 E4 V# l5 g w8 P `.end((err, res) => {` 0 Y8 x* L0 d4 H `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`5 h: _# R) h; C% I `$(``".course-item"``).each((i, v) => {`9 C8 B; }' W8 Z# G- S$ E8 M `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` # V( G& }" W0 w+ O* y2 j `const obj = {`& n) S# I0 T) r: _. y `imgSrc : $(v).find(``"img"``).prop(``"src"``),` # A. |/ C3 d1 [( S$ ?' ^/ n `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),` $ ^7 C$ o" J+ k2 a! ]5 Z( s9 K) ] `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` % R- T- z, S4 y+ j4 ] k `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`# t9 e* [, h. l `};` 3 u- [/ v$ P W" ]1 [8 ~ `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`" F# p6 |* T: ^- x7 L% ? `arr.push(obj);` `//把对象放进数组里` 4 f) g% x/ r( H7 ]& @ @ `});`% E1 M" ^1 P! i$ T( y S& T `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中` # T' _. P: B- ]; d6 ]% v6 H& L `});`
& f3 _: o* P) b: C% K1 Z

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

8 I6 {. R4 P7 S- n2 h , s( o: n) Z2 l6 w" L4 S 6 b2 q. c8 i- n/ f 1 |' o* x& ~8 L 2 ~: p, \: b0 P/ c( }2 P" e7 K
回复

举报 使用道具

相关帖子

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