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

[复制链接]
) V! y5 R% ^9 W/ J% r

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

, R3 S- B+ s( K5 X# E9 W1 g# D

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

0 Y" ~0 S5 n0 P' Y( d

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

$ K( F" d; u0 e, T# a* U

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

+ y/ \. a5 W" f8 C1 u! m

1.koa

& `* S+ r( W+ }) ?3 p

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

6 ]% }8 {: [0 ~

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

实例化对象: const app = new koa; & H; [' ?6 O2 t3 H4 Y2 s# B" f g

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

* T v9 O, i8 b4 g) C% f$ h

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

* w5 A. M5 M- ~! Z

其中有两个参数:

5 G3 w& h+ @" {8 s( Y& w$ s/ Q) \% x

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

) g7 z) ]7 J, H% H0 z! M% U$ ~

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

. ^! H( ^2 @0 v O% ~* `. s

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

/ _* H5 W9 p! i1 D+ @2 ?; x

1. next参数的使用demo

- q1 z4 r" L! G+ k
`const Koa = require(``"koa"``);` / }) e# z, ^2 Q9 |; p5 M/ ~' t `const koa =` `new` `Koa();` + _7 D9 K. x' r+ Z `//中间件1` # e1 Y+ }1 Y& z. @, U0 Z `koa.use(async (ctx, next) => {`* D3 K+ M6 V# }$ b `console.log(``"1 , 接收请求控制权"``);`1 V# ~ E ^+ N# o$ N `await next();` `//将控制权传给下一个中间件`+ ~3 m( e, Y0 C% T5 C$ H. S4 _ `console.log(``"1 , 返回请求控制权"``);` . \5 m% G: l: b( M2 y! A2 f `});` `//将中间件注册到koa的实例上`; s' p1 g/ ^8 z `//中间件2`% `# l; ^; W" ~7 X8 T4 j `koa.use(async (ctx, next) => {` , s! P. y) i0 h& [+ U5 c- K `console.log(``"2 , 接收请求控制权"``);` - s. M% \" e5 U/ x# W& A# O await next();`/ g# w* J. e( v+ F' q$ q9 q `console.log(``"2 , 返回请求控制权"``);`. H: V& F I- t/ R- ?3 G `});`% c4 B' W9 ]" F/ i6 Z& C `//中间件3` & \! D7 T2 K. E( l l `koa.use(async (ctx, next) => {` , i% }& |: d' B( W7 _3 _7 [ `console.log(``"3 , 接收请求控制权"``);`% r' }6 ^% w* r- [& a `console.log(``"3 ,返回请求控制权"``);` ; o- O. P) V* d! B! N0 G9 z `});` 9 w8 a# T9 N3 z1 {- ] `koa.listen(3000, ()=>{`' ^7 u2 [& X0 g/ c `console.log(``"开始监听3000端口"``);` I' f, s4 k* A1 f `});`
) D2 s# ?, M! `; y" |

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

$ [9 X: }2 i* o+ a7 F5 J" H1 Z

访问localhost:3000的效果图;

# X# ]% H/ u% S/ Z0 Q
0 U1 R7 O+ I. h* i8 K% l3 M6 M

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

& e% D! k5 x2 j! _# `6 S. i

2.ctx参数的使用demo

5 c! c9 U1 P, N) s( ~2 M
`const Koa = require(``"koa"``);` 1 T. S6 `9 r$ k0 Z; e3 b `const koa =` `new` `Koa();`& W9 a/ Y6 ~; F, U9 } `koa.use(async (ctx, next)=>{` ( i; d; c1 c' E) Y `ctx.body =` `"body可以返回数据,"``;` ; C' m- a( F& }& L/ W `ctx.body +=` `"可以多次调用,"``;`$ C ~9 E, m) F2 k; U/ w1 ` `ctx.body +=` `"不需要end()"``;` 0 ?0 H" n" I! T9 |/ f F, ^ `});`' I& t) h2 `; q' B `koa.listen(3000, ()=>{` & [( G7 R( a: f7 H `console.log(``"监听开始"``);`+ [( ?+ q0 n; ?9 @. y: W: ]. } `});`
3 P7 Q0 h9 ?2 }& J- b& J d

效果:

( p+ f% }6 J8 L
* t6 E5 T2 y t6 i( ^+ [3 H5 m

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

7 z9 G4 y2 N5 q9 H# J* C3 W
`const Koa = require(``"koa"``);`& w- Q( {) C3 z7 o0 }! n+ Z" G `const koa =` `new` `Koa();`: [+ f6 \( s! ~( }( m) r5 m `koa.use(async (ctx, next)=>{`" n- g$ g9 b1 Z2 o `ctx.body = ctx.url;` * F. O* P6 Q" x5 P `ctx.body = ctx.path;` $ n, Y. o9 V- e `ctx.body = ctx.query;`1 f# S E9 B2 X7 ` `ctx.body = ctx.querystring;` @+ Y9 E% V# \8 k6 w `});`3 @# G5 H1 e; N" l1 z `koa.listen(3000, ()=>{`( A. w' }5 U9 b6 G& l `console.log(``"监听开始"``);` + T2 W: ]7 _' Z" j, i0 W" t( | `});`
X0 z& O' j0 N

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

5 r$ h0 V; p. C$ x# O' A! \

1. url: 整个路径

0 S9 H& l! p4 G1 }% j* j
' z R: @5 z9 ^5 ]: {! i

2. path: 非查询部分

7 W9 B1 i; I% I5 K% ?
@% A7 v u" t, Z3 N; m

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

8 h1 g8 ?( a. a+ [# I' E* }% u
/ g& i+ f- ]8 J# S* t5 p( I: k

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

8 U% k: j0 l" Z- L! x
9 F4 I* c, ~/ C3 X) R

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

- U# {8 T% x2 F" {# c- c

2.简单爬虫练习

6 G- C' O1 S9 x

安装request,cheerio模块

4 ]* u! F& B. N) I) J
`npm i -S request: 请求模块` 5 G8 j( L/ w7 p; t0 n W) Y% ] `npm i -S cheerio: 抓取页面模块(JQ核心)`
6 [+ k! q. N( M0 {* j1 Z

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

3 |+ g$ `/ e1 f+ M& e$ E2 E
`//导入模块` ! w R9 O& A, J5 J `const request = require(``"superagent"``);` `//导入请求模块` ) J) o5 z+ M, b3 Z `const cheerio = require(``"cheerio"``);` ) I- A; e, A; \( o/ B3 @3 ^" H `const {join} = require(``"path"``);`4 w' b! Z: U# A `const fs = require(``"fs"``);`1 G0 S( }; D. _7 `+ [2 j9 [ `let arr = [],` `//存放数据`4 L8 Q6 c8 z+ }$ T) u$ m' c P `reg = /\n|\s+/g,` `//replace中使用`7 Z* K& a, p& p- X* Q `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/)"``;` . }7 ~! a) G( `8 [* P. ^ `request`1 U, m1 t8 Y4 T& M& ?# U `.get(url)`$ C4 }3 [! q7 K/ t ^ `.end((err, res) => {`5 ~6 u; n6 C. ]" |) ~ `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`% ]" U0 E4 H7 l, S9 e! w/ e `$(``".course-item"``).each((i, v) => {` ' r$ `7 j& H8 i' w* C. L: }$ a4 y' D `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` % E. A9 C% q! l8 W& \$ s. ]8 T `const obj = {`5 b! n, d9 n! n# I8 G `imgSrc : $(v).find(``"img"``).prop(``"src"``),` 0 {" h) l" s+ `1 t% H. B8 W `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`- q5 R8 r* p+ T( H `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` 1 j/ k) f, P/ Y5 c0 K: [, r `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`7 M$ {: R) v6 }! t4 O `};` 0 q: b- O9 u8 d2 D& s; Q `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` }, e; _4 B& x6 o0 f$ F `arr.push(obj);` `//把对象放进数组里` % a7 Q) E$ ]4 Y `});`1 p* q' v" S" }( G5 k+ t `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`! J7 z, N6 X8 K* A; ] `});`
' s b3 `8 e6 }' m* h" w: g2 H: k

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

& q, g# `) t$ u/ J; j, J+ Q1 W0 U. G/ B- _, p , Y* h+ {# | _0 A# @( \( m$ g* h ' F! _+ f2 L+ s
回复

举报 使用道具

相关帖子

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