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

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

[复制链接]
& f+ D" G2 N, d. g V. G$ \) O

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

9 a7 [0 A0 e3 }, x8 \

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

5 R! x) u5 ~9 F; B% L3 J) v2 X

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

0 P, W+ J$ Z; u2 l" ?& ~

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

2 I3 M8 S" L9 b' ^0 R' \

1.koa

+ g& T% c4 Y, d% u

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

_* \' u/ S) T4 R0 c

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

实例化对象: const app = new koa;+ A! e- O4 P3 x. X+ q0 M- n# `; m

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

3 J# \( q4 y/ M$ l% c) s8 S6 Y

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

; @8 I9 O* L" E3 d0 ~2 \% P6 ?6 `1 s

其中有两个参数:

0 v( ~+ v" U+ |* d @1 D

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

- V: ?6 Y5 d7 V4 o4 h

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

9 Z' U) S$ U2 w: f( F4 a! H

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

. S, @) g# t0 z1 h9 `, i: f9 o9 E

1. next参数的使用demo

$ y1 P: n1 G0 w
`const Koa = require(``"koa"``);`7 o) | t& K1 {" C; J `const koa =` `new` `Koa();`2 V4 y$ ~( p; l; T) r# C! c$ i% r8 l `//中间件1`' v1 |2 u7 O) W3 X `koa.use(async (ctx, next) => {`9 @; |9 \* R B/ m- e9 y `console.log(``"1 , 接收请求控制权"``);` & G* k- Y% h& L1 H: ^) E4 l. D0 e8 w `await next();` `//将控制权传给下一个中间件` / r$ l- H J) b `console.log(``"1 , 返回请求控制权"``);` 3 B" l1 ]9 K% [* V$ |$ G' d3 M `});` `//将中间件注册到koa的实例上` - d; Z7 f, o9 ~ w `//中间件2` ) P. S g! e( Q) L& [! m# n4 V `koa.use(async (ctx, next) => {`) t5 }0 s1 c, h3 J2 ?) u1 }( r! b `console.log(``"2 , 接收请求控制权"``);`6 G( C* _) M7 \3 R await next();`5 n/ E9 R/ B& ]! [$ @2 k6 { `console.log(``"2 , 返回请求控制权"``);`2 I) N& y& w5 y% B3 {* L% \; E5 q4 A `});`. p+ r0 u9 V6 ?# ]5 Q- U `//中间件3` 6 y+ i6 B4 H: V% H3 K4 w! K9 x1 V `koa.use(async (ctx, next) => {`" j* A, f8 d* O `console.log(``"3 , 接收请求控制权"``);`$ o4 z& Y$ O' l `console.log(``"3 ,返回请求控制权"``);`. p% J5 h* V4 `4 P# C `});`3 F7 u/ ^& L- } `koa.listen(3000, ()=>{` p! C+ ]0 G, @$ ~$ K# z1 | `console.log(``"开始监听3000端口"``);` - E2 g$ Z3 C- [9 F5 O l `});`
- R0 w; {; H5 H5 w4 o6 P5 N

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

5 Y9 f; _, Q' b, M

访问localhost:3000的效果图;

* y2 H% b: X$ E) M& C5 L. E
0 H t6 ^+ |. }* R8 U

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

: i) ]* c0 Q3 a% j, p0 M, e

2.ctx参数的使用demo

) Y& G9 L: o* Q+ _6 V! n
`const Koa = require(``"koa"``);` ; \- \$ t4 u$ z1 X5 |3 } `const koa =` `new` `Koa();`8 l) Y/ V4 ^8 y7 c1 L* @% d `koa.use(async (ctx, next)=>{` * l) @* b2 y/ ]' Z, p0 _ `ctx.body =` `"body可以返回数据,"``;` 4 N) q) M( n( r C. A/ F `ctx.body +=` `"可以多次调用,"``;`7 j1 e! p4 L) h Z! a `ctx.body +=` `"不需要end()"``;` 5 _/ P, [. A0 I6 D3 _1 k8 [ `});`$ B B. w7 K! f o `koa.listen(3000, ()=>{`/ l2 S8 g$ Z1 S$ M `console.log(``"监听开始"``);`2 F7 q( p& m# G4 [+ L- G3 { `});`
% e. X1 k+ e/ J3 n* J" z

效果:

/ n" w! O7 N% J. A0 R* u% a
( | [6 Y/ C1 d5 T# ]' U% J! u

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

& @8 ~0 |- y9 |# H F k( E6 k
`const Koa = require(``"koa"``);`& N" B0 ]9 v- Y& ~" r: s& o4 A6 v `const koa =` `new` `Koa();`9 l5 o( ~% F/ |6 y3 C! T `koa.use(async (ctx, next)=>{`8 ]+ r0 Q: R: l( n" u `ctx.body = ctx.url;`- i: l; Q* J( y8 t `ctx.body = ctx.path;` % d8 P3 W; O: p5 r* C `ctx.body = ctx.query;`% n) \/ r9 @2 h! V6 G2 w { `ctx.body = ctx.querystring;` + y% ~& o7 E) N& b3 a7 l- b `});` 5 @( Q* Q6 U/ n% }9 ~3 l `koa.listen(3000, ()=>{`2 l$ T/ L2 I- G: ]3 A5 J+ s `console.log(``"监听开始"``);` 5 l3 \" u% E4 e6 E4 v4 B l! [7 I `});`
/ U0 L0 P. I3 ]

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

4 h, m3 r. {; `8 U+ P. G* `

1. url: 整个路径

9 p4 \9 _* V- H& _ C
. c9 h+ S3 A" F# c7 ]0 @

2. path: 非查询部分

1 e5 x0 _: u9 g* q4 ]2 k3 b9 C
4 d/ U6 ?3 d9 X% P7 J

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

. B. j& P( W- e5 h6 F6 b
3 R* G. I2 l' J5 l* K$ V

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

# `& V8 s5 a3 G
! u0 b! f( }( q, ~# Z

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

$ U' t1 t ` d d

2.简单爬虫练习

, _- z# A* K2 J2 j6 v7 P d

安装request,cheerio模块

/ A! r6 R" j9 x8 S
`npm i -S request: 请求模块`. H; q5 p4 ?, X: C, D+ l$ q `npm i -S cheerio: 抓取页面模块(JQ核心)`
6 I5 n& D0 Y. ~* J

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

- N8 E" o9 Z+ s* q' e7 Z
`//导入模块`" h# k+ b: a3 ` b6 E `const request = require(``"superagent"``);` `//导入请求模块` # K. ]' ^8 }0 X" d `const cheerio = require(``"cheerio"``);` / ?* J; q0 a# D/ x$ P, V0 ` `const {join} = require(``"path"``);` 3 p, \ w9 p* f" K0 {& `) q. | `const fs = require(``"fs"``);` " H! t3 y. X/ E `let arr = [],` `//存放数据`8 t, Z; J a/ w# A5 w `reg = /\n|\s+/g,` `//replace中使用`5 [# ^$ F$ T3 x. T2 Z$ b `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/)"``;`+ M# V1 h* o. T w, ~( |$ s. L `request`7 W4 F9 B8 l% w8 d9 l) E `.get(url)` ' w% t/ e" N! Z+ X( i- s1 S( ?5 r `.end((err, res) => {` ( J: a' j1 f& `7 a; @1 b8 M `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用` 9 }+ \3 j; |; B* n `$(``".course-item"``).each((i, v) => {` / X! d5 X3 |$ ^5 w `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` # H( i! x) e4 N! E" R" [ `const obj = {`# }: Y, M: E5 P; d* x- A2 Z `imgSrc : $(v).find(``"img"``).prop(``"src"``),`; y+ r/ M( G2 w `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),` " Z7 m2 h+ O2 b! J) P5 j0 ^ `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`- Z' U+ c4 H* z `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`, Q: C- p+ ~1 v" H* |2 l! r `};`$ {! u7 w5 q% L l" ^" {1 b `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` / }/ v+ x( P! u$ M `arr.push(obj);` `//把对象放进数组里` O$ B4 A& N; Q9 I `});` 8 @) x1 G0 D% p% W# r# B `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中` * S- p# L7 k ~8 g: z' S1 \ `});`
/ d; t& ]0 J$ ^& y

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

: e& s' Q4 _$ U) T) e 1 K% H# n9 c5 U 4 B6 Q. f% y. r9 L8 F. `1 V% l0 | v; I" _. i7 C2 L9 y 1 q/ f' f5 M3 l4 ?$ A# J
回复

举报 使用道具

相关帖子

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