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

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

[复制链接]
" O3 f! R. E2 R0 `6 `

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

! b/ [7 u; W2 S' \: c9 H" [3 y

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

4 i0 Q0 w* i% G$ [$ b4 d j

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

u' h) S; [; O9 ~1 y

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

5 G& S# g) f" c* C6 c

1.koa

' S6 S4 H6 g" T, |( V; h: i+ g

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

9 T0 f7 ^% l( `7 N# a- Q7 y

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

实例化对象: const app = new koa; + H/ v# r/ o% q# M. ?# m

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

9 o: n8 U/ ^6 Q

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

" T' ]# U1 j! ^1 O

其中有两个参数:

5 F* L/ D% G, H9 |+ z: K! [

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

5 J7 f! z- k' p

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

8 I; ` x: i; _5 |: B

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

7 }3 @9 m1 {* J _1 U4 l

1. next参数的使用demo

# ?: W4 {4 P x0 n4 N- V* z$ d
`const Koa = require(``"koa"``);`3 e4 L. h% q2 e; Y5 y `const koa =` `new` `Koa();`$ O8 D& _2 u, s% Z% d0 M `//中间件1` " l2 I9 E2 D2 O2 k `koa.use(async (ctx, next) => {`: ^; k, q- |. B8 X+ d1 ?: X `console.log(``"1 , 接收请求控制权"``);`% L6 ^! D' p9 Q( T$ [ `await next();` `//将控制权传给下一个中间件` * B, m5 b) Z. S$ ?, s0 D `console.log(``"1 , 返回请求控制权"``);`8 ^* Z; J6 _7 `& {3 Z4 {$ e3 U `});` `//将中间件注册到koa的实例上`! G( k( X( R8 @" c3 m `//中间件2` 6 B: {% _. F* B `koa.use(async (ctx, next) => {` : i% I5 h1 t3 a% j- H4 B7 ]5 F5 ~ `console.log(``"2 , 接收请求控制权"``);` & j; Q9 K- \) y& c- D await next();` 6 ?' G5 W' I1 E `console.log(``"2 , 返回请求控制权"``);` ; R* ~% X; A( z+ g `});` 9 R' @8 F# e5 s0 L `//中间件3` / S7 K y) N+ L5 X+ @7 `( K `koa.use(async (ctx, next) => {`) ^, f: c0 }6 E) I# m `console.log(``"3 , 接收请求控制权"``);` 8 _( p. |2 M7 |. V `console.log(``"3 ,返回请求控制权"``);` 0 P% M# o; v: a `});` 3 y& a' l; E+ F `koa.listen(3000, ()=>{`- S" w9 z1 R2 |+ a `console.log(``"开始监听3000端口"``);`& W p. Q/ y! o+ ?' V0 D7 f3 R, e `});`
3 d. V) ?' O7 Z" Z; W7 p9 {. s

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

- t- |! a% l5 R* Q a+ S1 B

访问localhost:3000的效果图;

: r) J3 q# s) y. D
; U% a8 W1 M/ ~: H1 b4 L2 g" ?

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

) F& [3 F% |* S* N

2.ctx参数的使用demo

, R$ Z) `6 X) t; C+ a e
`const Koa = require(``"koa"``);`# M9 w0 z5 V4 m* b `const koa =` `new` `Koa();` 8 C0 b. a! [/ c `koa.use(async (ctx, next)=>{` 7 c2 W. U. c; m5 o `ctx.body =` `"body可以返回数据,"``;` ! ^) t7 ~ P- E& s0 Z; R1 c `ctx.body +=` `"可以多次调用,"``;`; H3 ?; n6 v. U, q7 G `ctx.body +=` `"不需要end()"``;`1 I" [6 h2 l+ T! W( o0 ?" r `});` 1 d* U6 \2 J; K0 B. y# g `koa.listen(3000, ()=>{` 6 }+ B0 ^' n* q1 ]! `; M7 w `console.log(``"监听开始"``);`. o1 S* Q6 B# {+ z7 U% W `});`
! P) o% m& f' s6 m

效果:

+ ?7 T W; X+ \( _& j
5 E1 B. O, V: c) d; s' j

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

4 ~% N1 j6 g% H% |. I
`const Koa = require(``"koa"``);` . G1 Y1 D$ ~$ K/ X7 Q8 P: W `const koa =` `new` `Koa();`3 E$ e' `2 q( L! F$ T, z& Y! t `koa.use(async (ctx, next)=>{` % F c1 N- k" I7 B5 S& G `ctx.body = ctx.url;` ( n) q6 c9 D5 H `ctx.body = ctx.path;` 3 q9 p6 }2 ~+ F' t; T) l `ctx.body = ctx.query;`1 H( {) m* S+ r `ctx.body = ctx.querystring;` & k3 ~. @% O5 z `});` % B: }/ w: J3 g3 [, L `koa.listen(3000, ()=>{`8 v% F; j* @: y; _ `console.log(``"监听开始"``);` 7 Z8 g7 m9 A2 _. |: O& [( ^ `});`
3 ]5 T1 V: A* B

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

3 A) d6 F7 F# I k c

1. url: 整个路径

6 |' z, Q7 @7 z; }
. W3 [& ~; e- g) w0 Z& l& @

2. path: 非查询部分

4 E C) s' \7 @7 x1 u- T
( o+ N3 V5 l) n

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

0 Z3 {3 i- w2 ]/ P1 ` \
4 |! W; y) S4 b0 n9 c, @0 L% x: c

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

) p6 d* O9 M6 ]2 I/ g. t- E
e2 h2 F) n/ z

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

0 W* K7 i/ d8 A( v7 r$ ^! W* [

2.简单爬虫练习

$ g' }' v5 P6 w0 _ G3 D4 j1 F! J L

安装request,cheerio模块

) l3 C: b# A9 C7 y5 k6 I6 T& P& q
`npm i -S request: 请求模块` 3 S; P4 z, s5 l+ c: P/ `2 E' A1 n `npm i -S cheerio: 抓取页面模块(JQ核心)`
( J% U- a6 P% F2 \

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

6 @3 d& `& C l, O
`//导入模块`& Q$ e7 x4 n% o# f `const request = require(``"superagent"``);` `//导入请求模块`4 E0 u" i. M8 y* w7 N t3 e, ?' R* L `const cheerio = require(``"cheerio"``);` Q( O" v* P3 F# d& ^ `const {join} = require(``"path"``);`/ P8 }0 s, b6 x5 j `const fs = require(``"fs"``);`3 q- b3 p* @! I `let arr = [],` `//存放数据`" G% k' Z( U/ j1 {! R `reg = /\n|\s+/g,` `//replace中使用` ; x. i: T0 S. Z# \# t3 B4 Y! t `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/)"``;`5 I( u+ S- q8 Y( F. Q `request`0 }# f) U% J7 x; N `.get(url)`' v2 A1 A; G, B* a: Q `.end((err, res) => {`3 o5 |# C6 o, q2 K `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`3 x8 b d/ h# a* ]9 ?, F `$(``".course-item"``).each((i, v) => {`3 x% c$ t, K S' S `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`1 \" l$ N( o$ y( \% ? `const obj = {`2 N9 C; y1 Q1 ?7 n `imgSrc : $(v).find(``"img"``).prop(``"src"``),` 9 G3 j4 N& ]1 U; A0 m' W5 f# i# M U `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),` - z' M- p9 |$ s3 y, M `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` 1 {: a/ s. F9 V. n* s7 I `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))` ! c4 p2 G4 K, A) j k2 s `};` 7 i( b5 V! e& V3 K7 S+ o6 z1 c `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` - M9 ?: j: r4 T" Q6 A- r# s `arr.push(obj);` `//把对象放进数组里` 2 G& {) _0 E" S- V `});`) \3 T* _9 Z6 D9 M; `6 `7 T `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`: U1 p- j& V# \( W `});`
& h/ n0 B* R o

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

6 U6 N9 Z' c1 A1 ~; F) u, P# ?0 P. y% _$ @ ) U0 E. O9 w) g b% t2 R- B7 ?5 P' @+ ` i+ j - b" D4 ?2 N. J' L, M) L4 d
回复

举报 使用道具

相关帖子

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