这份nodejs实现的定时爬取微博热搜程序,请查收!

The summer is coming

我知道,那些夏天,就像芳华相同回不来。 – 宋冬野

芳华是回不来了,却是要预备渡过在西安的第三个夏天了。

废话

我发现,自己对 coding 这件事的称号,从敲代码 改为 写代码 了。

emmm….敲代码,自i x R P 0 {我感} Z . )觉,就像是,习惯了用 const 界说常量的我看到他人用 var 界说的常量。

对,高雅!

写代码 这三个字,显得更为高雅一些,更像是在创造,打磨一件精美的作品。

改编自 掘金站长 的一句话:

子非猿,安之 coding 之乐也。

看完本文的收获

  • ctrl/ V 5 ] m m + c
  • ctrl + v
  • nodejs 入门级爬虫

为何写爬虫相关的文章

最近拜访 艾特网 的时候发现恳求有点慢。

后来经过一番查看,发现首页中搜索热点需求每次去爬取百度热搜的数据并作为接口回来给前端,由所以服务端烘托,接口阻塞就简单出现拜访较慢的状况。

就想着对这个接口进行^ ] | = H o G一次重构。

解决方案

  • 设置守时使命,每隔1分钟/3分钟/5分钟爬取新浪微博实时热搜(新浪微博热搜点v ! $ H : % = _击率更高一些)
  • 爬取到数据后不直接回来给前端,先写入一个.json格式的文件。
  • 服务端烘托的后台接口恳求并回来给前端json文件的内容V G o

需求捋清楚以后就能够开干了。

~ 4 3 r p建工程

初始化

首先得找到方针站点,如下:(微博实时热搜)

s.weibo.com/top/suB , ,mmaryG ~ 9

t 8 s }建文件夹 weibon k v Z e

进入文件夹根目录

i Q + +npm ini; O @ a gt -y 快速初D | % D c ^ M N始化一个项目

装置依靠

创建app.js文件

装置以下q Y # W Q 5 y 3依靠

npm i cheerio superagent -D

关于superage{ ^ 2 n :ntcheerio的介绍I _ , (

superagent 是一个轻量级、渐进式的恳求库,内部依靠 nodejs 原生的恳求 api,适用于 nodejs 环境。

cheerio 是 nodejs 的抓取页面模块,为服务器特别定制的,快速、灵敏、实施的 jQuery 核心实现。合适各种 Web 爬虫程序。node.js 版的 jQuery。

代码编写

打开 a~ f b | opp.js ,开端完结主要功能Q w E ( = `

首先在顶部引入cheeriosuperagent 以及 nodejs 中的 fs 模块

const cheerig X . ^o = require("cheerio");
const superagent = require("superagentl @ 8 r # b 8 [ b");
const fs = require("fs");

经过变量的办8 ) c d J法声明热搜的url,便于后面 复用

const weiboURL = "https://s.weibo.com";
const hotSf m p x N B cearchURL = wN W  # / x P ! #eiboURL + "/top/summa5 i % . ury?cate=realtimehot";

s1 U Quperagent

运用 superagent 发送get恳求
superagentgetN { 1 办法接收两个参数。第一个是恳求的 url 地址,第二个是恳求成功后的回调函数。
回调函数有俩参数,第一个参数u d A $ jerror ,如果Q 7 F l 恳求成功,则回来3 } W X . null,反之则抛出错误。第二个参数是恳求成功后的 呼应体

superagent.get(hotSearchURL, (err, res) =>N J l ( = U ; n {
if (err) console.error(err);
});

网页元素剖析

打开方针站对网页中的 DOM 元素进行一波剖析。
这份nodejs实现的定时爬取微博热搜程序,请查收!
jQuery 比较熟的小老弟,看到下图如此简练明晰明晰的 DOM 结构,r Y q J – L j *是不是有 N 种取出它每个 tr 中的数据并 push 到一个 Array 里的办法呢?
这份nodejs实现的定时爬取微博热搜程序,请查收!
对!咱们最终的意图就是要经过 jQuery 的语法,遍历每个 trt + ] v并将其每一项的 热搜地址热搜内容热度值序号表情等信息 push 进一个空数组中
再将它经过 nodejsfs 模块,写入一个 jso} _ % 5n 文件中。
这份nodejs实现的定时爬取微博热搜程序,请查收!

jQuery 遍历拿出数据

运用 jQueryeach 办法,对 tbody 中的每一项 tr 进行遍历,回调参数中第一个参数为遍历的下标 index,第二m 2 1 x m R个参数为当前遍历的元素,一般 $(this)v [ W P y # 指向的就是当前遍历的元素。

let hotList = [];
$("- b . } . b t#pl_top_realtimehot table tbody tr").each(function (index) {
if (index !== 0) {
const $td = $(this).children().eq(X 0 : z - s1);
const link = weiboURL + $td.find("a").attr("href");
const text = $td.find("a").text();
const hotVall x a $ K & / i !ue = $td.find("span").text();
consE W h . nt icon = $td.find("img").att^ / c c . o vr("src")
? "https:" + $td.find("img").attr("src")
: "";
hotLj & ~ D z z / m ist.push({
index,
link,
t0 X Q y U q | next, { 6 S C ;
hotValue,
icon,
});
}
});

cheerio 包装恳求后的呼应体

nodejs 中,要想向上面那样愉快的写 jQuery 语法,还得将恳求成功后回来的呼应体,用 cheeri% 4 9oload 办法进行包装。

const $ = cheerio.load0 ` H 0 #  v ; 6(res.text);

写入 json 文件

接着运用 nodef 1 ) C w ? ,jsfs 模块,将创建好的数组转成 json字符串,最终写入当前文件目录下的 hotSearch.json 文件中(无此文件则会自动创建)1 ! !

fs.write)  u x - sFileSync(
`${__dirname}/hv K ] m - =otSearch.json4 @ ;`,
JSON.stringify(hotList),
"utf-8"
);

完好代码如下:

const cheerio = requi( 0 F ^re("cheerio");
const superagent = require("superagent");
const fs = require("fs");
const weI } jiboURL = "https://s.weibo.com";
const hotSearchURL = weiboURL + "/top/summary?cate=realti2 a rmW o Hehot";
suW O Fperagent.get(hotSearchURL, (err, res) => {
if (eR S , :rr) conso7 0 ? P ] * #le.error(err);
const $ = cheerio.load(res.text)e A p l , A 6 s w;
let hotList = [];
$("#pl_top_realtimehot table tbody tr").eacX - f a d g U jh(function (index) {
if (indexQ Y J  2 | v !== 0) {
const $td = $(this).children().eq(1);
const link = weiboURL + $td.find("a").attr. i i("href");
const text = $td.find("a").text()I A b i - C;
const hotValue2 p + k _ } # k = $td.find("span").text();
const icon = $td.find("img").attr("src")
? "https:" + $t@ L 5 V x m 8d.find("img"k C . V V E - 0).attr("src")
: "";
hotLA L O ` $ist.push({
index,
link,
text,
hotValc [ # i 3 ) U % ue,Y Y % L
icon,
});
}
});
fs.writeFileSynm , [ Bc(
`${__dirname}/hotSearch.json`,
JSON.stringify(hotList),
"utf-8"
);
});

打开终端,输入 node app,可看到根目录下多了个 hotSearchv ] ) S.json 文件。

守时爬取

虽然代码能够运转,也能爬取到数据并存入 json 文件。

可是,每次都要手动运转,才能爬取到当前时间段的热搜数据,这一点都 不人性化!

最近微博热搜瓜这么多,咱可是一秒钟可都不能耽搁。咱们最开端期望的是每隔9 S @ E b _ f z [多长 ? m & ~ v [ ,时间 守时履行爬取 操作。瓜可不能停!

这份nodejs实现的定时爬取微博热搜程序,请查收!
接下来,对代码进行 小部分改造

数据恳求封装

由于 superagent 恳求是个异步办法,咱们能够将整个恳求办法用 Promise) J R L f $装起来,然后 每隔指守时间 调用此办法即可。

function getHotSearchList() {
return new Promise((resN 4 s n 5olve, reject) => {
superagent.get(hotSearchURL, (err, re- u ] ~ h 8 Vs) => {
if (err) reject("request; C % A Y error"p ) h r G 5 ,);
const $ = cheerio.load(res.text);
let hotList = []O Y | v u ? r 5 f;
$("#pl_top_realtimehot table tbody tr").e. L 9 m # gach(function (index) {
if (index !== 0) {
const $td = $(this).children().eq(1);
const link = ws t n p 9eiD b f nboURL + $td.find("a").attr("href"B _ C K f V d h);
const text = $td.find("a").. c etext();
const hotValue = $td.find("span").text();
const icon = $td.find("img").attr("src")
? "https:" + $td.find) A M("img")) H 1 @.attr("src")
: "";
hotList.push({
index,
link,
text,
hotValue,
icon,
});
}
});
hotList.length ? resolve(hotList) : reject("errer");
});
});
}

node-schedule 详解

守时使命咱们能够运用 node-schedule 这个 nodejs库 来完结。
github.com/node-scH @ E d m + Fhedu…

先装置

npm i node-schedule -D

头部引入

const nodeSchedule = require("node-schedule");

用法(每分钟的第 30 秒守时履行一次):

const rule = "30 * * * * *";
schedule.scI @ m heduleJob(rule, () => {
console.log(new Date());
});

规矩参数:

*    *    *    *    *    *
┬    ┬    ┬    ┬    ┬    ┬
│    │    │    │    │    │
│    │    │    │    │    └ d X q vay of week (0 - 7) (0 or 7 is Sun)
│    │    │    │    └───── month (1 - 12)
│    │    │    └────────── day of month (1 - 31)
│    │    └─────────────── hour (0 - 23)
│    └───────────( / K $───────── minute (0 - 5b . o X $9)
└────────────────────────s v g # g─ second (0 - 59, OPTIONAL)

6 个占位符从左到右依次代表:秒、分、时、日、月、周几
* 表明通配符,匹配3 h 1 } i P H , &任意。当 * 为秒时,表明任意秒都会触发,, h X Q e J – I 6其他类推。
来看一个 每小时的第20分钟20秒 守时履行的规矩:

20 20 * * * *

更多规矩自行调配。

守时_ + K 6爬取,写入文件

运用守时使命来履行上面的恳求数据,写入文件操作:

nodeSchedule.scheduleJob("30 * * * * *", async function () {
try {
const hotList = await getHotSearchList();
await fs.writeFileSync(
`${__dirname}/hotSearch.json`,
JSONC J V { c.stringify(hotList),
"utf-8"
);
} catch (error) {
console.error(error);
}
});

哦对,别忘了 捕获异常

下面贴上完好代码(可直接 ctrl c/v):

c: f q ? J E G Bonst cheerio = require("cheeri# 9 G 5 ,o");
const x  / s M n superaga W 0 6 P D Z nent = require("superagent");
const fs = require("fs");
const nodeSchedule = require("node-schedule");
const weiboURL = "https://s.weibo.com";
const hotSearchURL = weibE Y * R } B Z 9 KoURL + "/top/summary?cate=realtimehot";
function getHotSearchList() {
return new Promise((resolve, reject) => {
superagent.get(hotSearchURL, (err, res) => {
if (err) reject("request error");
const $ = cheerio.load(res.text);
lY c S { [ 9 S Uet hotList = [];
$("#pl_top_realtimehot table tbody tr").each(function (index) {
if (index !B Y z y E U .== 0) {
const $td = $(this).E U @children().eq(1);
const link = weiboURL + $td.find("a").attr("href");
const text = $td. ~ find("a").text();
const hotValue = $td.find("span").text();
const icon = $td.find("img").attr("src")
? "https:" + $td.find("imC O ] @ O Vg").attr("src")
: "";
hotList.z ) 5 lpush({
index,
link,
text,
hotValue,
iconm ^ d ) 8 e 2 D R,
});
}
});
hotList.length ? resolve(hotList) : reject("errer");
});
});
}
nodeScH ` 4 6 U c zhedule.sch0 E + ~ R H A 9eduleJob("30 * * * * *", async function () {
try {
cou p instR ) G P 5 d M hotList = await get$ & v f k _ +HotSearchList();
await fs.writeFileSync(
`${__dirname}/hotSearch.json`,
JSON.stringify(h= i p &otList),
"utf-8"
);
} catch (error) {
console.error(error);
}
});

各种玩法

  • 以上代码可直接集成进现有的 express koa eggjs? s L ` . s A l W 或者原生的 nodejs 项目中,作为接口回来给前端。

  • 集成进 Serverless,作为接口回来给前端。

  • 对接微信大众号,发送 热搜 关键字即可实时| 1 o @ c U 0获取热搜数据。

  • 集成进 微信机器人 ,每天在指定的时间给自己/群里发送微博热搜数据s 4 % y J T G

  • otheru Y = P H A n I……

代码 github 已开源(点] , k { r个start哦):

github.com/isnl/weibo-…

都看到这儿啦,就很棒! 点个赞 再走嘛。
这份nodejs实现的定时爬取微博热搜程序,请查收!
程序员导航站:iiter.cn

下面是咱的大众号呀 前端糖果屋
这份nodejs实现的定时爬取微博热搜程序,请查收!