nodejs实现定时爬取微博热搜
The summer is coming
”
我知道,那些夏天,就像青春一样回不来。 - 宋冬野
青春是回不来了,倒是要准备渡过在西安的第三个夏天了。
废话
我发现,自己对 coding 这件事的称呼,从敲代码 改为 写代码 了。
emmm....敲代码,自我感觉,就像是,习惯了用 const 定义常量的我看到别人用 var 定义的常量。
对,优雅!
写代码 这三个字,显得更为优雅一些,更像是在创作,打磨一件精致的作品。
改编自 掘金站长 的一句话:
”
子非猿,安之 coding 之乐也。
看完本文的收获
ctrl + c ctrl + v nodejs 入门级爬虫
为何写爬虫相关的文章
最近访问 艾特网 的时候发现请求有点慢。
后来经过一番检查,发现首页中搜索热点需要每次去爬取百度热搜的数据并当做接口返回给前端,由于是服务端渲染,接口堵塞就容易出现访问较慢的情况。
就想着对这个接口进行一次重构。
解决方案
设置定时任务,每隔 1分钟/3分钟/5分钟爬取新浪微博实时热搜(新浪微博热搜点击率更高一些)爬取到数据后不直接返回给前端,先写入一个 .json格式的文件。服务端渲染的后台接口请求并返回给前端 json文件的内容
需求捋清楚以后就可以开干了。
创建工程
初始化
首先得找到目标站点,如下:(微博实时热搜)
https://s.weibo.com/top/summary?cate=realtimehot
创建文件夹 weibo
进入文件夹根目录
使用 npm init -y 快速初始化一个项目
安装依赖
创建app.js文件
安装以下依赖
npm i cherrio superagent -D
关于superagent和cherrio的介绍
”
superagent 是一个轻量级、渐进式的请求库,内部依赖 nodejs 原生的请求 api,适用于 nodejs 环境。
”
cherrio 是 nodejs 的抓取页面模块,为服务器特别定制的,快速、灵活、实施的 jQuery 核心实现。适合各种 Web 爬虫程序。node.js 版的 jQuery。
代码编写
打开 app.js ,开始完成主要功能
首先在顶部引入cheerio 、superagent 以及 nodejs 中的 fs 模块
const cheerio = require("cheerio");
const superagent = require("superagent");
const fs = require("fs");
通过变量的方式声明热搜的url,便于后面 复用
const weiboURL = "https://s.weibo.com";
const hotSearchURL = weiboURL + "/top/summary?cate=realtimehot";
superagent
使用 superagent 发送get请求
superagent 的 get 方法接收两个参数。第一个是请求的 url 地址,第二个是请求成功后的回调函数。
回调函数有俩参数,第一个参数为 error ,如果请求成功,则返回 null,反之则抛出错误。第二个参数是请求成功后的 响应体
superagent.get(hotSearchURL, (err, res) => {
if (err) console.error(err);
});
网页元素分析
打开目标站对网页中的 DOM 元素进行一波分析。

对 jQuery 比较熟的小老弟,看到下图如此简洁清晰明了的 DOM 结构,是不是有 N 种取出它每个 tr 中的数据并 push 到一个 Array 里的方法呢?

对!我们最终的目的就是要通过 jQuery 的语法,遍历每个 tr ,并将其每一项的 热搜地址 、热搜内容 、 热度值 、序号 、表情等信息 push 进一个空数组中
再将它通过 nodejs 的 fs 模块,写入一个 json 文件中。

jQuery 遍历拿出数据
使用 jQuery 的 each 方法,对 tbody 中的每一项 tr 进行遍历,回调参数中第一个参数为遍历的下标 index,第二个参数为当前遍历的元素,一般 $(this) 指向的就是当前遍历的元素。
let hotList = [];
$("#pl_top_realtimehot table tbody tr").each(function (index) {
if (index !== 0) {
const $td = $(this).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("img").attr("src")
: "";
hotList.push({
index,
link,
text,
hotValue,
icon,
});
}
});
cheerio 包装请求后的响应体
在 nodejs 中,要想向上面那样愉快的写 jQuery 语法,还得将请求成功后返回的响应体,用 cheerio 的 load 方法进行包装。
const $ = cheerio.load(res.text);
写入 json 文件
接着使用 nodejs 的 fs 模块,将创建好的数组转成 json字符串,最后写入当前文件目录下的 hotSearch.json 文件中(无此文件则会自动创建)。
fs.writeFileSync(
`${__dirname}/hotSearch.json`,
JSON.stringify(hotList),
"utf-8"
);
完整代码如下:
const cheerio = require("cheerio");
const superagent = require("superagent");
const fs = require("fs");
const weiboURL = "https://s.weibo.com";
const hotSearchURL = weiboURL + "/top/summary?cate=realtimehot";
superagent.get(hotSearchURL, (err, res) => {
if (err) console.error(err);
const $ = cheerio.load(res.text);
let hotList = [];
$("#pl_top_realtimehot table tbody tr").each(function (index) {
if (index !== 0) {
const $td = $(this).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("img").attr("src")
: "";
hotList.push({
index,
link,
text,
hotValue,
icon,
});
}
});
fs.writeFileSync(
`${__dirname}/hotSearch.json`,
JSON.stringify(hotList),
"utf-8"
);
});
打开终端,输入 node app,可看到根目录下多了个 hotSearch.json 文件。
定时爬取
虽然代码可以运行,也能爬取到数据并存入 json 文件。
但是,每次都要手动运行,才能爬取到当前时间段的热搜数据,这一点都 不人性化!
最近微博热搜瓜这么多,咱可是一秒钟可都不能耽搁。我们最开始期望的是每隔多长时间 定时执行爬取 操作。瓜可不能停!

接下来,对代码进行 小部分改造。
数据请求封装
由于 superagent 请求是个异步方法,我们可以将整个请求方法用 Promise 封装起来,然后 每隔指定时间 调用此方法即可。
function getHotSearchList() {
return new Promise((resolve, reject) => {
superagent.get(hotSearchURL, (err, res) => {
if (err) reject("request error");
const $ = cheerio.load(res.text);
let hotList = [];
$("#pl_top_realtimehot table tbody tr").each(function (index) {
if (index !== 0) {
const $td = $(this).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("img").attr("src")
: "";
hotList.push({
index,
link,
text,
hotValue,
icon,
});
}
});
hotList.length ? resolve(hotList) : reject("errer");
});
});
}
node-schedule 详解
定时任务我们可以使用 node-schedule 这个 nodejs库 来完成。
https://github.com/node-schedule/node-schedule
先安装
npm i node-schedule -D
头部引入
const nodeSchedule = require("node-schedule");
用法(每分钟的第 30 秒定时执行一次):
const rule = "30 * * * * *";
schedule.scheduleJob(rule, () => {
console.log(new Date());
});
规则参数:
* * * * * *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ │
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
│ │ │ │ └───── month (1 - 12)
│ │ │ └────────── day of month (1 - 31)
│ │ └─────────────── hour (0 - 23)
│ └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, OPTIONAL)
6 个占位符从左到右依次代表:秒、分、时、日、月、周几
* 表示通配符,匹配任意。当 * 为秒时,表示任意秒都会触发,其他类推。
来看一个 每小时的第20分钟20秒 定时执行的规则:
20 20 * * * *
更多规则自行搭配。
定时爬取,写入文件
使用定时任务来执行上面的请求数据,写入文件操作:
nodeSchedule.scheduleJob("30 * * * * *", async function () {
try {
const hotList = await getHotSearchList();
await fs.writeFileSync(
`${__dirname}/hotSearch.json`,
JSON.stringify(hotList),
"utf-8"
);
} catch (error) {
console.error(error);
}
});
哦对,别忘了 捕获异常
下面贴上完整代码(可直接 ctrl c/v):
const cheerio = require("cheerio");
const superagent = require("superagent");
const fs = require("fs");
const nodeSchedule = require("node-schedule");
const weiboURL = "https://s.weibo.com";
const hotSearchURL = weiboURL + "/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);
let hotList = [];
$("#pl_top_realtimehot table tbody tr").each(function (index) {
if (index !== 0) {
const $td = $(this).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("img").attr("src")
: "";
hotList.push({
index,
link,
text,
hotValue,
icon,
});
}
});
hotList.length ? resolve(hotList) : reject("errer");
});
});
}
nodeSchedule.scheduleJob("30 * * * * *", async function () {
try {
const hotList = await getHotSearchList();
await fs.writeFileSync(
`${__dirname}/hotSearch.json`,
JSON.stringify(hotList),
"utf-8"
);
} catch (error) {
console.error(error);
}
});
各种玩法
以上代码可直接集成进现有的
expresskoaeggjs或者原生的 nodejs 项目中,作为接口返回给前端。集成进 Serverless,作为接口返回给前端。
对接微信公众号,发送
热搜关键字即可实时获取热搜数据。集成进 微信机器人 ,每天在指定的时间给自己/群里发送微博热搜数据。
other......
都看到这里啦,就很棒! 点个赞 再走嘛。

程序员导航站:https://iiter.cn
下面是咱的公众号呀 前端糖果屋

代码 github 已开源:
https://github.com/isnl/weibo-hotSearch-crawler
nodejs实现定时爬取微博热搜的更多相关文章
- Python网络爬虫-爬取微博热搜
微博热搜的爬取较为简单,我只是用了lxml和requests两个库 url=https://s.weibo.com/top/summary?Refer=top_hot&topnav=1& ...
- BeautifulSoup爬取微博热搜榜
获取url 设定请求头 requests发出get请求 实例化BeautifulSoup对象 BeautifulSoup提取数据 import requests 2 from bs4 import B ...
- Python爬取微博热搜以及链接
基本操作,不再详述 直接贴源码(根据当前时间创建文件): import requests from bs4 import BeautifulSoup import time def input_to_ ...
- 【网络爬虫】【java】微博爬虫(一):小试牛刀——网易微博爬虫(自定义关键字爬取微博数据)(附软件源码)
一.写在前面 (本专栏分为"java版微博爬虫"和"python版网络爬虫"两个项目,系列里所有文章将基于这两个项目讲解,项目完整源码已经整理到我的Github ...
- 2020不平凡的90天,Python分析三个月微博热搜数据带你回顾
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:刘早起早起 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...
- 第一个nodejs爬虫:爬取豆瓣电影图片
第一个nodejs爬虫:爬取豆瓣电影图片存入本地: 首先在命令行下 npm install request cheerio express -save; 代码: var http = require( ...
- python3爬取微博评论并存为xlsx
python3爬取微博评论并存为xlsx**由于微博电脑端的网页版页面比较复杂,我们可以访问手机端的微博网站,网址为:https://m.weibo.cn/一.访问微博网站,找到热门推荐链接我们打开微 ...
- C#爬取微博文字、图片、视频(不使用Cookie)
前两天在网上偶然看到一个大佬OmegaXYZ写的文章,Python爬取微博文字与图片(不使用Cookie) 于是就心血来潮,顺手撸一个C#版本的. 其实原理也很简单,现在网上大多数版本都需要Cooki ...
- 纯前端实现词云展示+附微博热搜词云Demo代码
前言 最近工作中做了几个数据可视化大屏项目,其中也有用到了词云展示,以前做词云都是用python库来生成图片显示的,这次用了纯前端的实现(Ctrl+V真好用),同时顺手做个微博热搜的词云然后记录一下~ ...
随机推荐
- PTA数据结构与算法题目集(中文) 7-7
PTA数据结构与算法题目集(中文) 7-7 7-7 六度空间 (30 分) “六度空间”理论又称作“六度分隔(Six Degrees of Separation)”理论.这个理论可以通俗地阐述为 ...
- Kubernetes Pod钩子
目录 1.Pod容器钩子最终目的 2.何为Pod容器钩子 3.基于PostStart演示 4.基于PreStop演示 5.优雅停止Java应用 1.Pod容器钩子最终目的 之前在生产环境中使用dubb ...
- Linux 权限管理篇(一)
可读 r 可写 w 可执行 x 档案属性: 第一栏:执行list -al后第一栏的十个标志[1 - 10] 1: d 目录 - 档案 l 连 ...
- Mysql大数据量问题与解决
今日格言:了解了为什么,问题就解决了一半. Mysql 单表适合的最大数据量是多少? 我们说 Mysql 单表适合存储的最大数据量,自然不是说能够存储的最大数据量,如果是说能够存储的最大量,那么,如果 ...
- tf.nn.dropout 激活函数
tf.nn.dropout(x,keep_prob,noise_shape=None,seed=None,name=None) 参数: x:一个浮点型Tensor. keep_prob:一个标量Ten ...
- Juli函数
- 一站式WebAPI与认证授权服务
保护WEBAPI有哪些方法? 微软官方文档推荐了好几个: Azure Active Directory Azure Active Directory B2C (Azure AD B2C)] Ident ...
- 【Jenkins】参数化引用
我们在Jenkins里设置了参数如下 1. Jenkins中引用 shell引用 $env windows bat引用 %env% 在git等源码管理时,调用参数的格式${env} 2. jmete ...
- C. Beautiful Regional Contest
用前缀和写一直wa.. 思路:让金牌和银牌最少,通多增加铜牌的方式来扩大总奖牌的个数. #include<bits/stdc++.h> using namespace std; map&l ...
- Jmeter系列(3)- Jmeter安装目录介绍
如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html Jmeter安装目录说明 bin:包含 ...