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

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

[复制链接]
2 `9 X; s7 }2 a' ? S8 @

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

2 w4 `/ P0 V+ B) H3 Q# t; A7 j

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

/ D1 E7 J0 L, ]3 b# P& p

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

; ~9 t, t9 e& v3 C) [

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

* ]! w7 c8 \! i" `' t$ R2 T

1.koa

3 _& r/ p s$ H& H \

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

. }! Y* @# E0 T( R" y# J+ S; y

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

实例化对象: const app = new koa;9 r! O, g! G; a" L- C5 R5 ]1 W

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

# X C! V$ I' v# x! ?

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

. q4 \* X2 d6 N, I( [2 T. h" @0 B8 Z

其中有两个参数:

# S: x$ k, w% a; J# Q

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

) |" D* }) C0 M1 T! A u9 B

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

% j! j7 d" S# x* Y5 i, u! o2 r, A3 S

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

2 }& {- e% t- H9 ~+ T, ~

1. next参数的使用demo

% J, T$ N/ @: ?( S& H& f
`const Koa = require(``"koa"``);`! ~9 |8 u+ p4 [# ?% U9 d `const koa =` `new` `Koa();` 5 U, `8 g* K& o `//中间件1` 5 }) y$ Z# g' c: ?- B `koa.use(async (ctx, next) => {` ' B# q6 A" @2 s$ k# c2 ^ `console.log(``"1 , 接收请求控制权"``);` - j* S" i9 ^. t) O2 D) Q( l/ q `await next();` `//将控制权传给下一个中间件` " d! t& i J" G; ?: I) L' X; q `console.log(``"1 , 返回请求控制权"``);` 3 g0 x( C P: [1 e/ i, J! p1 x `});` `//将中间件注册到koa的实例上` 6 \" [1 K# f* b& s/ y `//中间件2`# }, E0 ] I O, T1 E- n `koa.use(async (ctx, next) => {`" Y: @5 n% Z" }' F9 q' a `console.log(``"2 , 接收请求控制权"``);` " d' D8 ], q/ } await next();`/ i+ t( @6 l$ o* L8 X `console.log(``"2 , 返回请求控制权"``);` ! f! [+ g" e, ~: a' B8 W# E `});` 2 }2 Q: D1 b, e' i `//中间件3`, G4 L. n! G1 R. }* `% g `koa.use(async (ctx, next) => {`1 f$ z+ M8 B" e' ^8 [0 B `console.log(``"3 , 接收请求控制权"``);`# j# v) P6 A! I0 L9 ?8 U& W5 t. m: u `console.log(``"3 ,返回请求控制权"``);`! ~" v+ B5 q. A2 b& ~ `});`- ~( ^# r4 C" C' F1 _ `koa.listen(3000, ()=>{`7 S$ q( Y" q8 B X# m$ \ `console.log(``"开始监听3000端口"``);` M; E; z! L" k `});`
+ S/ w( ~/ w$ K' V( N, j

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

3 H' r. Z- I) V5 J. { v% g/ `/ i$ _" \

访问localhost:3000的效果图;

4 I/ ?1 q; b3 F
) Q$ |" ?$ E* a

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

% K- o. F) z' z" D

2.ctx参数的使用demo

( A9 ] \ k# y% [; Z4 x7 ~
`const Koa = require(``"koa"``);` 0 \# z, W3 P& [/ X d `const koa =` `new` `Koa();` 0 |- p( G( W$ A6 a' B. e `koa.use(async (ctx, next)=>{`/ ?: D0 _2 `7 Y8 S, t( A- [' v `ctx.body =` `"body可以返回数据,"``;` ! i. o2 `9 _2 Q; k9 ?0 S4 Q `ctx.body +=` `"可以多次调用,"``;`! m( D) L9 w6 f' k" w: M `ctx.body +=` `"不需要end()"``;`( {! V3 W0 G/ t; e `});`" g+ f" l1 Q( p) \ `koa.listen(3000, ()=>{` / @. E/ H8 X' x0 }# p1 l" C$ @% D7 E `console.log(``"监听开始"``);` ( w8 x4 G8 e: I T1 ] `});`
3 [: F+ u6 a+ W5 |: `

效果:

& ~& ^7 f2 m& h" r4 w4 X8 T; c. P
8 N9 o d; U# U/ a' o9 i

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

7 k. {/ A' V( h$ S- ^0 [
`const Koa = require(``"koa"``);` $ C" N! b9 _; m' E6 r; U3 \ `const koa =` `new` `Koa();` 9 u( v" W# K4 N J) m1 [. L `koa.use(async (ctx, next)=>{`9 V6 p0 P# F, c& R) ] `ctx.body = ctx.url;` ]# e* A, h$ o1 b `ctx.body = ctx.path;`; W7 k+ k% i( N: J2 ?6 w- ? `ctx.body = ctx.query;` 5 u( U9 z$ ]; _' U1 W `ctx.body = ctx.querystring;`, p2 H, o; [9 | `});`6 k) y6 M, h9 y5 B7 S$ v `koa.listen(3000, ()=>{`3 W, O$ @5 b, h) z; y3 ] `console.log(``"监听开始"``);` 1 v s+ a: b }* y. K, d `});`
3 q* d: J: y- G `; u

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

. o9 j8 S8 z+ w+ M! h' M P; G

1. url: 整个路径

1 h/ {, d! {& f/ |3 c
; k+ G. s4 \: M+ Q7 @# J

2. path: 非查询部分

; z( V5 O2 J$ q1 z8 l6 W* f
$ R9 \+ d+ d6 |

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

! m, w2 ~) }4 b% b6 q1 d. o
; x0 f+ ^5 @6 ]- u6 K% V

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

' l' `5 i' _8 W4 Q2 H) z
) J m, k) B1 b: E% q. ~9 L" X

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

, {- I, A' s; c: N. h

2.简单爬虫练习

+ ?$ L2 T+ w) X' A8 O

安装request,cheerio模块

* f H0 O/ m, i3 P% {
`npm i -S request: 请求模块`1 g! w* t5 [5 Y( L `npm i -S cheerio: 抓取页面模块(JQ核心)`
, l- Y# e) r/ W) r; \

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

\7 _7 C) z% q7 }
`//导入模块`6 h6 ~$ n5 @1 F9 A& V5 ?# v `const request = require(``"superagent"``);` `//导入请求模块`3 Z* s( K& `! b0 s6 {. U" \1 g7 o `const cheerio = require(``"cheerio"``);` : ]$ J' _+ S4 \$ g; ]4 k; I+ J8 n `const {join} = require(``"path"``);` 5 q; o9 x( L* U5 q2 Y `const fs = require(``"fs"``);` 2 z% a8 b( T: n+ i$ e `let arr = [],` `//存放数据`; C0 W+ p1 b7 U- S9 D% ` `reg = /\n|\s+/g,` `//replace中使用` ' `6 e7 P6 J% h* M+ Z, Q! q1 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/)"``;` , {: _# Q* T; m3 [, O! | `request`9 p; {$ ^0 a/ K" E `.get(url)` 7 X) v+ L8 { ~. G* s# d8 }* F m% Y `.end((err, res) => {`! ^( B! c2 s3 J7 R# ~ `const $ = cheerio.load(res.text);` `//把字符串内的标签当成dom来使用`& q3 Z+ f3 {3 j' ]! z6 V3 | `$(``".course-item"``).each((i, v) => {`4 c& i$ c6 u3 K- Y `// v当前进来的dom,根据网页的布局结构来找到准确的dom节点`3 ]: U% F6 u. z7 I: _ `const obj = {` - i" O# i: E# O3 \& y" h9 h `imgSrc : $(v).find(``"img"``).prop(``"src"``),` ) |( W N3 Q7 Y& o0 [ `price : $(v).find(``".fr span"``).text().replace(reg,` `""``),`; x- ^9 R$ \$ w `total : $(v).find(``".item-txt"``).text().replace(reg,` `""``),`1 o2 t& A) l6 z2 X' X `href : join(url + $(v).find(``".cimg"``).prop(``"href"``))` 3 V, c+ J9 Y& c* y, E `};` ' z3 t( d7 g% v/ U. w; k( } `console.log(join(url + $(v).find(``".cimg"``).prop(``"href"``)));` `//拼接`# k/ p2 Y" D+ n `arr.push(obj);` `//把对象放进数组里`- B. ]- g& X4 e/ ?9 m6 k* x6 D+ I, G `});` # V5 _! s# a, w' V- L' g `fs.writeFile(``"./sjl.json"``, JSON.stringify(arr));` `//将爬到的数据写入文档中` o' v0 e5 ~/ G$ A8 ^ f! k" l `});`
# w/ w% ]3 ]5 k1 I4 ~% U8 k7 l6 @

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

3 | c/ b0 w- G2 y * v$ C- E1 D3 [' N0 p 9 v, M/ T! r# w% f9 B0 f7 j3 W+ I& Q0 f: l1 A + L1 ?2 s* h) I" @* d7 u0 X4 E3 d$ k
回复

举报 使用道具

相关帖子

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