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

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

[复制链接]
' l9 e X* ?2 b3 t, Z; C3 a. c

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

; E& q- s5 }8 B6 b: O) b

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

/ I9 H! e- ? f% H/ Q7 `9 l7 u

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

2 u4 j0 i. f& I

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

8 x- u. a* P4 r: W- X

1.koa

( a) E* `1 Z8 O6 j* d4 b k4 F& W

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

4 X/ ~- h! w" J

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

实例化对象: const app = new koa;4 g2 Q. o% ?9 ~' m5 g: Z

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

: T' ~! R2 R& a) T0 {# @

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

' V& J5 X" U* p0 }

其中有两个参数:

' ^5 F) G; T3 {, H

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

z3 e( T3 q( ?2 U4 R. J

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

7 e S; W; P3 J" M; h/ w

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

& W9 R2 R1 m' D' I- M1 _

1. next参数的使用demo

8 ]% _. P5 ~0 y
`const Koa = require(``"koa"``);` 4 i) O6 S+ u' H `const koa =` `new` `Koa();`2 P' F2 N1 @( e% g0 f9 n+ I `//中间件1`) u) P4 j! x8 a8 h/ d% G! L f `koa.use(async (ctx, next) => {` ; u, V z1 I* k `console.log(``"1 , 接收请求控制权"``);`8 H4 P2 w, p3 B0 L' A* G `await next();` `//将控制权传给下一个中间件`4 V5 E- ?# n$ e `console.log(``"1 , 返回请求控制权"``);`7 S; h( s. I& ^/ A n `});` `//将中间件注册到koa的实例上`* l7 e* J2 `1 v9 M# i- h9 @$ S `//中间件2`5 d7 i' o! u$ L4 \ `koa.use(async (ctx, next) => {`- J* F% H/ ?/ Y# b, L `console.log(``"2 , 接收请求控制权"``);`. Z" h4 }$ l l8 i await next();`* G- f5 s( u P% z' T& Q `console.log(``"2 , 返回请求控制权"``);` 5 D4 C# d x, r9 N6 M3 h; a. P `});` A5 ?% a; ]3 D" c' g2 N `//中间件3`+ `4 y' s! M2 c# P, i r `koa.use(async (ctx, next) => {`* F+ W8 n" t5 F/ F" v% s, W! |" Q `console.log(``"3 , 接收请求控制权"``);` 4 m, s; \: t/ b# T, T' G `console.log(``"3 ,返回请求控制权"``);` z/ F1 R: ^7 b) [ `});`4 }) r1 w" N5 p4 Y8 r' n1 u `koa.listen(3000, ()=>{`) s1 ^7 W9 P. c1 f' y `console.log(``"开始监听3000端口"``);` 8 I& Z7 Q5 Q+ o! S' U* F `});`
/ Y4 J0 Q- Q: g, z! y# G

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

; k$ G3 h B' M4 a- L4 j

访问localhost:3000的效果图;

; L i: z2 S0 ?% g7 t9 D4 j
: W6 E% A& s. f1 t' }

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

7 @" D* m W+ Q5 r) h+ k% v

2.ctx参数的使用demo

( t$ w& Y e+ I3 y, l3 G+ z
`const Koa = require(``"koa"``);`; x" R0 ^' J0 _8 x `const koa =` `new` `Koa();` 2 \; K5 g6 Q, k+ P; i5 P9 B5 S `koa.use(async (ctx, next)=>{`2 y0 h! f- Z& O `ctx.body =` `"body可以返回数据,"``;` % U5 A6 P5 U" W `ctx.body +=` `"可以多次调用,"``;`' X. P0 P/ o+ F6 O& ^9 }- T `ctx.body +=` `"不需要end()"``;` 1 A1 U2 X! z" k" B4 B6 @ `});`7 Y' X8 ^" f' ? `koa.listen(3000, ()=>{` 7 P. ^2 V* A, ?, ?$ u# S+ B `console.log(``"监听开始"``);`3 e! z; @1 i' z7 j$ s5 X% L9 u `});`
, s z7 ?) t; z3 G- n- \

效果:

& d" y, r5 J" V' |3 g2 t* n: j3 O+ ]
N0 i. |# _6 _/ Z$ g6 F/ a: N

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

% I1 u, }. ~( {/ E- c! s
`const Koa = require(``"koa"``);` 3 ?/ d# O4 c1 X! R( I, Q0 F+ R# ]6 m `const koa =` `new` `Koa();`: E& S! s* C! K- I4 w2 [: k/ Y- O8 I M `koa.use(async (ctx, next)=>{` 9 U! X0 n- }% z! M0 P1 a3 @6 R `ctx.body = ctx.url;`. Z% r# u, t: [9 O `ctx.body = ctx.path;` 7 E1 k P5 D D8 p1 B7 c2 f `ctx.body = ctx.query;`% t" r+ K3 E. n$ b `ctx.body = ctx.querystring;`5 R$ {1 \# e( ^ `});` 4 F o/ c/ k" H, F `koa.listen(3000, ()=>{`# b( ?3 J1 L: | `console.log(``"监听开始"``);`. \ L6 U2 A1 k: W5 M0 m `});`
& f% Z( f3 y6 N8 H, F, c; v. k; O

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

/ g! M- z0 E. i# p

1. url: 整个路径

& Y: ]$ `& B6 n$ L3 B" f
4 r/ a+ F* ?3 a8 l e

2. path: 非查询部分

9 M# x- I4 K9 q& k# X
( B N3 m0 y1 B, |

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

2 B5 E& a$ B9 U0 y7 Q4 i) @
8 k6 R) Y3 ?4 G& T4 {

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

$ h" f3 x2 T$ D( X# o: V
8 l9 m! G6 F6 ?# x

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

4 U4 |' y; Y. I& i# P

2.简单爬虫练习

6 d, A# z/ k3 y3 O. C# R& e% l( l

安装request,cheerio模块

: V% R! V0 o% a* R( {
`npm i -S request: 请求模块` U; y9 ^7 N) T6 a& V1 }" u/ p S `npm i -S cheerio: 抓取页面模块(JQ核心)`
" _% k* X0 e, s) C3 \' f# D# f

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

% A& q+ V4 j; T* x4 A3 a
`//导入模块`+ B( J# z) f1 a) W. t `const request = require(``"superagent"``);` `//导入请求模块` ' r( f6 o( \& |. U& ~' j4 A `const cheerio = require(``"cheerio"``);`7 G# O- ]( \$ u `const {join} = require(``"path"``);` 3 o. k1 ]1 p8 B4 `9 H" ~* O0 n6 x `const fs = require(``"fs"``);`# b1 f5 b/ p6 M; Z% y* @8 J `let arr = [],` `//存放数据`( R3 c, ^, y( {0 V `reg = /\n|\s+/g,` `//replace中使用`; ?8 C& H+ t y) N) u! Z) k `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/)"``;` & O" [* g4 B* d; n9 P/ [1 B `request` # `9 w- f$ d: C9 o+ I `.get(url)`% F. D6 t* i/ Y+ l" ^/ p `.end((err, res) => {` T# P. s/ K) r; t2 ? `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`: x9 F0 B, K9 Z& L) A2 ` `$(``".course-item"``).each((i, v) => {`9 Z% u {2 d- I0 O) d1 W$ D `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点` & T% f4 ?) f& V `const obj = {`& x, `; d) o+ c9 o `imgSrc : $(v).find(``"img"``).prop(``"src"``),` ! `7 F, ?: a! f1 t0 ?3 ^ `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`$ t# b; H1 r G; H0 M" b `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),` ' n4 d8 ~, v* u `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))`/ }' a( W. d% R5 ]. x `};`. ]3 J4 o0 |5 i& D, A `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接` 6 X% e$ U* A% r: Y& p, y `arr.push(obj);` `//把对象放进数组里` 7 S; Z+ y, i' d `});`7 \3 x- }8 ^/ v2 e `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中`) V3 i2 ~9 O) l `});`
' i) b" v- y+ _" M( K

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

$ Z( D0 Q- o! A$ Z " R/ _; L5 W, `& G0 t: @# `% u- G3 f3 \1 I& u: W " L5 [0 ?* l" e! H5 z& {/ R$ i# S. B. ^( s1 `
回复

举报 使用道具

相关帖子

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