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

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

[复制链接]
2 C" i: e* C3 U. E7 x3 _( \4 j+ v) m

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

! t0 A" \7 P- R" Z+ I' A

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

6 ~5 ]4 _; _; ]; A k

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

! @5 s9 K. v: V! t6 X: D

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

! g# p; q& R m% {$ r: d; }

1.koa

3 g" V8 P% Q b& ?

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

" C. k# s% v3 O' q$ k

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

实例化对象: const app = new koa;" |& B( ^* l! v4 L/ U! j* p

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

: ^9 R3 x% c/ H! h" @

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

0 |/ H0 w+ B; B0 ]7 \% q

其中有两个参数:

1 f/ q {, e3 y2 l+ ^0 `$ W

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

/ k0 H5 \' h. u8 ]

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

/ @, }; ]3 V( M# h. f

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

% ~! T/ N, A2 c) a7 R

1. next参数的使用demo

X7 F, p0 j h- x" e" S; t
`const Koa = require(``"koa"``);` $ W- [) z' n1 R$ g E5 i$ U \ `const koa =` `new` `Koa();`+ x9 Y! a/ U$ j/ {% b `//中间件1`& ~3 \1 I2 c- G0 s8 p h. x `koa.use(async (ctx, next) => {` # x" l! p. F6 H4 E% D! x `console.log(``"1 , 接收请求控制权"``);`& k( x' u. w$ B9 J, g `await next();` `//将控制权传给下一个中间件` * v$ ], ?: e( n+ E3 l7 V- D% { `console.log(``"1 , 返回请求控制权"``);`2 v4 r1 p) \& J* M; ?) N `});` `//将中间件注册到koa的实例上` J( j" }/ ^$ Q4 D) j v `//中间件2` ' U c: I$ T0 ?5 \ `koa.use(async (ctx, next) => {`- h0 T. ?8 P0 }( k' Q5 A. d n `console.log(``"2 , 接收请求控制权"``);` 1 w6 j8 ^) u! V) r3 `2 N- ?$ I await next();`% k7 A$ j' ~4 D5 d% O `console.log(``"2 , 返回请求控制权"``);`+ V0 r1 J- t* A0 q$ R l7 }6 v `});`6 h6 c W9 @, c4 O' e, g `//中间件3`$ V: }5 [5 R$ H# Y; N C `koa.use(async (ctx, next) => {`# o. F6 n. I. b2 e: r, t0 M& S `console.log(``"3 , 接收请求控制权"``);`0 Y5 z1 Y& h) n4 V& { `console.log(``"3 ,返回请求控制权"``);` # }& B( G* p6 v `});`6 f$ G% _# Z) _9 @4 O `koa.listen(3000, ()=>{` 1 ]6 \8 M! r; S `console.log(``"开始监听3000端口"``);`8 `& I$ l- [( N m8 k8 ^ `});`
% U) y$ F$ s* }% J

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

, x. U9 J1 _9 @2 b

访问localhost:3000的效果图;

0 J& f1 _! f( Y3 H
5 G3 P% n- j" _) _, `0 b3 g

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

- ~( E/ ?' M- B, C

2.ctx参数的使用demo

0 l' {3 ?. j4 ~5 m; Q4 g Y ^
`const Koa = require(``"koa"``);`2 _6 `6 j! O/ r& T" f8 _ `const koa =` `new` `Koa();`; G! V% J" C/ B* D4 m `koa.use(async (ctx, next)=>{`1 o2 @1 |9 g+ g0 M9 @ `ctx.body =` `"body可以返回数据,"``;`7 V4 V" d6 r6 i8 [$ V9 b: R `ctx.body +=` `"可以多次调用,"``;` $ {: o3 d) m2 [4 K' \ Z+ J, S$ O `ctx.body +=` `"不需要end()"``;` 9 C j K1 c/ D; x `});`5 U* i0 H, Q y5 R& ?- W2 y5 q+ r `koa.listen(3000, ()=>{` / h4 Z9 g; t1 N `console.log(``"监听开始"``);` ' J, L3 V9 e+ f' v3 Z# w8 r `});`
) P2 W2 l& N5 B/ G" ~& z+ H

效果:

6 d9 g( k# M3 P* B" I
, d* j3 L5 A# `+ G/ d6 |

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

+ j6 ~- p6 u; x* `/ T1 m: E
`const Koa = require(``"koa"``);`2 i7 u6 h8 v' y `const koa =` `new` `Koa();` 9 h( n0 x6 _2 w1 j `koa.use(async (ctx, next)=>{` " D& G3 Y5 b" `( J$ y# I: I0 V0 y `ctx.body = ctx.url;`- d' v5 A7 ^! e" g- x `ctx.body = ctx.path;`/ s( \% c0 B" ^' J% }7 m* g `ctx.body = ctx.query;`5 J3 _7 Q8 [* m* D' D `ctx.body = ctx.querystring;`) p3 } P. c: s* U E- e& g6 Y P- R! k `});`% }( N$ R4 v, v2 U9 [5 C8 c `koa.listen(3000, ()=>{`% A! P8 E) f7 D0 h `console.log(``"监听开始"``);`, T0 m) A, R# }. | `});`
0 `. G' {, t2 o2 _6 g

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

4 @3 e$ |3 Q2 v9 d% B

1. url: 整个路径

9 b; t& e0 `0 s4 p1 L+ \$ O+ q
6 _* U, y# `/ k! [8 O+ e8 X( D

2. path: 非查询部分

/ y' N" \6 S4 n' ?& l5 }0 C
4 r/ e2 G# X! p! b. g. Z

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

$ o3 O# [3 {9 Y' Q+ x/ X$ F1 V8 s0 c
* M% B, ?4 {3 I- q$ m

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

1 Y5 F" X2 R, [' f+ v4 H9 z
9 O! Z& S0 V6 k

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

' J- g4 H4 }7 y9 f3 X

2.简单爬虫练习

* l% ?* Q& M; u' Z

安装request,cheerio模块

; a4 }( X3 e1 r2 y \% s- Q
`npm i -S request: 请求模块`( e( T7 r$ s) Q4 K0 _+ o `npm i -S cheerio: 抓取页面模块(JQ核心)`
) s/ v' s' x2 B8 Y+ l8 n) m

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

( g- l0 J- C/ F
`//导入模块`; G9 P& N. T. s$ U `const request = require(``"superagent"``);` `//导入请求模块` ' b! A7 |1 b; e `const cheerio = require(``"cheerio"``);`& J0 x* k+ u/ W9 U" [* d* Z `const {join} = require(``"path"``);`& f: Z- ?1 Y) }3 ]; L0 A3 U2 o- d: B `const fs = require(``"fs"``);` ! W7 F+ N( u' h- `6 _- q `let arr = [],` `//存放数据` 6 |; [7 F# s, \' {2 f4 E8 D: \' K `reg = /\n|\s+/g,` `//replace中使用`- ? G& n; y( V1 C( k! Z8 ^0 O `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/)"``;` 9 S# n! @9 K! ?7 I, a `request` & A5 y1 v0 ?9 x4 J `.get(url)`% C1 Q5 g. o0 u" M3 J# W `.end((err, res) => {` / D4 ^! i3 r$ T+ T5 H `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`! B+ O* C: Z5 J; p) P `$(``".course-item"``).each((i, v) => {`" ?( Y+ B: i& o `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`* F8 `% O. n, d' [: R `const obj = {`# w7 ]' f+ h7 D6 O7 ] `imgSrc : $(v).find(``"img"``).prop(``"src"``),` 5 j0 T: J' Z" j7 j S6 ^ `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),` ) q! J* \! |. Z4 c9 X8 { `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`, K& c2 l2 k3 B `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`. Z% X2 g! C+ D3 V q) l1 z2 y' R- } `};` $ M( a! T3 K3 S( B& w+ R `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` + R+ y- W o& _8 N5 E; T# e `arr.push(obj);` `//把对象放进数组里` 9 j( I4 F; n2 s2 F: m' a `});` 1 Q0 }4 r+ g1 P% | `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`. b' g2 X6 Q) K1 i" x6 m: ]* S' ` `});`
5 F# u" w9 }. ^$ S

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

; V+ p! S/ E5 d2 N/ {/ D/ ^ ! r0 x# a8 C" `2 U$ Q 8 l p8 K. ]7 p4 s % n8 j0 g- ]# o# B G9 c. r ~, e5 J; d% l- B. j( h
回复

举报 使用道具

相关帖子

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