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

[复制链接]
/ s4 W k8 F1 M/ B

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

8 v2 \# I+ ?- r" S' E; M& o5 T o

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

8 \4 _. @' Q* P% J) Z' C5 r

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

9 ?4 W3 r$ M0 L' X* Q& l5 q

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

( z- S& Q# l+ \2 |0 b, Z5 v

1.koa

3 h9 U' P# W& o" R F

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

; I( |2 k& g4 n) \8 o# {1 X( f" Q

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

实例化对象: const app = new koa; , _1 X9 z( {6 a, W6 Y

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

6 w% b2 p6 J {& `! e A- n- T: |

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

0 N. B' @, i" L$ x4 l" i

其中有两个参数:

3 ?/ N0 G/ J+ d3 T" D0 r

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

% R+ | i1 z, }) V$ g

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

9 |& b0 Z+ |, M$ e/ w x

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

% G% J j3 N& o

1. next参数的使用demo

7 E! j5 i z* H
`const Koa = require(``"koa"``);` & e# v' r$ @. Q: g `const koa =` `new` `Koa();`, F: H6 v' x7 H2 p `//中间件1` ; q& h3 ~" I N' V `koa.use(async (ctx, next) => {`& H( b" _7 Q* s/ t2 }. l+ ^ `console.log(``"1 , 接收请求控制权"``);` U0 V! q' ]" o4 E4 E0 }9 \ `await next();` `//将控制权传给下一个中间件`: [9 a) V4 }8 }8 l4 W `console.log(``"1 , 返回请求控制权"``);` 4 J5 p0 Z1 y+ I% l `});` `//将中间件注册到koa的实例上` 1 S( ?7 O% [! w! I- z& I: F1 G `//中间件2`/ L1 z6 |0 i: [5 M! V8 \4 A `koa.use(async (ctx, next) => {` & d: M. ?7 o- c8 R4 v- M `console.log(``"2 , 接收请求控制权"``);` ; z4 J7 F$ p% ?/ s, u! o' n2 E await next();`4 [7 |$ x1 T h4 M3 E7 E. \ `console.log(``"2 , 返回请求控制权"``);`$ }- n" A( t5 U) ^ `});`& X% u& n# \* a0 @9 g `//中间件3`5 y: q1 W; c2 W: H* ~ `koa.use(async (ctx, next) => {` ) t7 w1 t# g/ L1 |* B! P8 X% d `console.log(``"3 , 接收请求控制权"``);`! ^5 i$ ]7 \$ c& I! J `console.log(``"3 ,返回请求控制权"``);`: ^3 j. w+ P% i `});`7 P D, N& w% e/ c8 K! h2 ^ `koa.listen(3000, ()=>{` 4 @3 e+ l( ^5 }6 h `console.log(``"开始监听3000端口"``);` 2 N) g$ o" `$ m' d% P9 P `});`
, c/ |& Y* J7 D7 u$ {2 O) ~& I

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

2 T+ R/ R+ N4 a" y( h6 Z! L

访问localhost:3000的效果图;

/ P" s2 d1 R6 Z9 I" Z) n
3 o y m, a) r% r8 s

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

! k- I% j' s: _. ]) F- R

2.ctx参数的使用demo

4 g" l9 p$ X- j5 r" e1 K
`const Koa = require(``"koa"``);` / J% ~: ]1 W7 } b, f7 W$ Z `const koa =` `new` `Koa();` ) w2 P5 T- ~4 p& e) c' l, Q `koa.use(async (ctx, next)=>{` 4 X" R- u5 A( ^2 U3 v `ctx.body =` `"body可以返回数据,"``;` : r% u A( g8 J5 M \ `ctx.body +=` `"可以多次调用,"``;` , C3 F! g9 D7 l7 d3 g+ t! U. M `ctx.body +=` `"不需要end()"``;`3 R% P9 R9 v2 d1 ]. ^0 | `});` . j5 q7 Q/ n& e* ?+ N4 F `koa.listen(3000, ()=>{`+ [" R9 Y# B4 T* D `console.log(``"监听开始"``);` 4 Y% O+ S; j6 s! ^# r# S3 V2 `- ] `});`
. n+ D1 E! B" J

效果:

; P2 v' A$ m" g7 q/ K: d
, [) B3 g0 o# d$ Y

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

$ m9 o2 y& U) U/ N
`const Koa = require(``"koa"``);`% v/ {9 [9 J5 J6 y7 n+ P4 P& D' d `const koa =` `new` `Koa();` r* p" n8 d `$ r' C1 z3 P `koa.use(async (ctx, next)=>{`$ t6 J4 U0 P9 Y9 g6 ^0 X% g `ctx.body = ctx.url;` 7 s# i! n) t) v6 z( J6 b `ctx.body = ctx.path;` / M+ p( |6 W8 Q3 Z) j \ `ctx.body = ctx.query;` & ?: D% s* c1 c) X8 z$ K4 K `ctx.body = ctx.querystring;`" Z1 C1 w$ V2 ~, p `});` ; K; v2 K, \8 r" f. [5 [ m `koa.listen(3000, ()=>{`/ a: a2 Z5 }9 }. J" Y `console.log(``"监听开始"``);` 4 X0 E( h, [8 q j/ n" q' o `});`
) M, ~3 W* W/ i) R# q/ y( T! N

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

1 h" W6 X& ^; x- E: z

1. url: 整个路径

; X: }& q# x8 C& K; w& j
|4 g% a: J4 j4 q" i. R5 T# c. N

2. path: 非查询部分

! y" p4 C+ W9 d; S- ?- {; c
+ ^, y! q3 Y8 M( q6 \

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

X* V: L0 z8 H4 v: [7 f6 ~
5 \# t2 i4 n' K* G' [+ m! @ z+ f

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

- M1 r( }/ O, M/ t8 n! O/ `
5 b( A' c5 A2 _/ |0 ~

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

1 N# w0 R) E$ R. }) E

2.简单爬虫练习

3 U5 g, S0 i; W, c* K+ ]( s

安装request,cheerio模块

' }% P/ @& T) x
`npm i -S request: 请求模块` ( q$ ^. j, L! S C2 z2 D) Y `npm i -S cheerio: 抓取页面模块(JQ核心)`
4 q: i2 c/ ?0 M8 ^) Q$ T/ P

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

/ z$ O; P3 f$ v( V
`//导入模块` [ O/ x+ n( z$ V, | `const request = require(``"superagent"``);` `//导入请求模块`2 [5 }3 D) e' k6 Y0 x! F$ T0 Z( P `const cheerio = require(``"cheerio"``);`- e$ x. @$ i9 E* Q# ^ `const {join} = require(``"path"``);`; I9 L5 }% f8 \$ E8 h1 s/ u3 S# k `const fs = require(``"fs"``);` l$ a5 Y9 L* G9 w) k3 z9 G- U8 X. J `let arr = [],` `//存放数据`6 }/ u% L3 b5 m0 B/ E `reg = /\n|\s+/g,` `//replace中使用`. `8 P# z- a) S+ S# P `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/)"``;`8 C V* E* a; `: e9 k# M% X1 ^ `request`; e# {. \) v9 N! y `.get(url)` 8 ]4 Q# ^1 o% ?2 R7 P' a `.end((err, res) => {` ' ]2 S A7 w; W3 I Y7 V `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`6 e4 f: v* H6 r. F$ q, L8 h2 U `$(``".course-item"``).each((i, v) => {`+ Q2 I$ w: i: D' f" c* E F `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` & C, b2 g% J5 Q `const obj = {` 8 |% }6 h3 \6 g) W# g! y. v# H0 w `imgSrc : $(v).find(``"img"``).prop(``"src"``),` 7 b0 c% U3 e* Q' _& a6 j `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`; { p# I# S2 i, }' [( j `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`! B4 X& ?' X F `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`; f, m: l8 _; z) `3 E J `};`+ Y: y( d* K3 o `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`3 L- J: H2 V0 i6 M `arr.push(obj);` `//把对象放进数组里`1 a; t6 [. p/ P: X( y5 d% H6 S `});`( h; w7 z' @5 F+ S `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`) O' l* e4 V% m `});`
) u7 o2 { T, a1 K6 U

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

. h. P) c/ D6 m; \ 0 m. ?0 @ I$ [( K 9 `8 @+ H5 z1 z T. N) \: \ E \' L# D ; N8 d4 k. Z" {
回复

举报 使用道具

相关帖子

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