日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

nodejs实现定时爬取微博热搜

發(fā)布時(shí)間:2023/12/10 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nodejs实现定时爬取微博热搜 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

程序員導(dǎo)航站:https://iiter.cn

The summer is coming

我知道,那些夏天,就像青春一樣回不來。 - 宋冬野

青春是回不來了,倒是要準(zhǔn)備渡過在西安的第三個(gè)夏天了。

廢話

我發(fā)現(xiàn),自己對(duì) coding 這件事的稱呼,從敲代碼 改為 寫代碼 了。

emmm…敲代碼,自我感覺,就像是,習(xí)慣了用 const 定義常量的我看到別人用 var 定義的常量。

對(duì),優(yōu)雅!

寫代碼 這三個(gè)字,顯得更為優(yōu)雅一些,更像是在創(chuàng)作,打磨一件精致的作品。

改編自 掘金站長 的一句話:

子非猿,安之 coding 之樂也。

看完本文的收獲

  • ctrl + c
  • ctrl + v
  • nodejs 入門級(jí)爬蟲

為何寫爬蟲相關(guān)的文章

最近訪問 艾特網(wǎng) 的時(shí)候發(fā)現(xiàn)請(qǐng)求有點(diǎn)慢。

后來經(jīng)過一番檢查,發(fā)現(xiàn)首頁中搜索熱點(diǎn)需要每次去爬取百度熱搜的數(shù)據(jù)并當(dāng)做接口返回給前端,由于是服務(wù)端渲染,接口堵塞就容易出現(xiàn)訪問較慢的情況。

就想著對(duì)這個(gè)接口進(jìn)行一次重構(gòu)。

解決方案

  • 設(shè)置定時(shí)任務(wù),每隔1分鐘/3分鐘/5分鐘爬取新浪微博實(shí)時(shí)熱搜(新浪微博熱搜點(diǎn)擊率更高一些)
  • 爬取到數(shù)據(jù)后不直接返回給前端,先寫入一個(gè).json格式的文件。
  • 服務(wù)端渲染的后臺(tái)接口請(qǐng)求并返回給前端json文件的內(nèi)容

需求捋清楚以后就可以開干了。

創(chuàng)建工程

初始化

首先得找到目標(biāo)站點(diǎn),如下:(微博實(shí)時(shí)熱搜)

https://s.weibo.com/top/summary?cate=realtimehot

創(chuàng)建文件夾 weibo

進(jìn)入文件夾根目錄

使用 npm init -y 快速初始化一個(gè)項(xiàng)目

安裝依賴

創(chuàng)建app.js文件

安裝以下依賴

npm i cheerio superagent -D

關(guān)于superagent和cheerio的介紹

superagent 是一個(gè)輕量級(jí)、漸進(jìn)式的請(qǐng)求庫,內(nèi)部依賴 nodejs 原生的請(qǐng)求 api,適用于 nodejs 環(huán)境。

cheerio 是 nodejs 的抓取頁面模塊,為服務(wù)器特別定制的,快速、靈活、實(shí)施的 jQuery 核心實(shí)現(xiàn)。適合各種 Web 爬蟲程序。node.js 版的 jQuery。

代碼編寫

打開 app.js ,開始完成主要功能

首先在頂部引入cheerio 、superagent 以及 nodejs 中的 fs 模塊

const cheerio = require("cheerio"); const superagent = require("superagent"); const fs = require("fs");

通過變量的方式聲明熱搜的url,便于后面 復(fù)用

const weiboURL = "https://s.weibo.com"; const hotSearchURL = weiboURL + "/top/summary?cate=realtimehot";

superagent

使用 superagent 發(fā)送get請(qǐng)求
superagent 的 get 方法接收兩個(gè)參數(shù)。第一個(gè)是請(qǐng)求的 url 地址,第二個(gè)是請(qǐng)求成功后的回調(diào)函數(shù)。
回調(diào)函數(shù)有倆參數(shù),第一個(gè)參數(shù)為 error ,如果請(qǐng)求成功,則返回 null,反之則拋出錯(cuò)誤。第二個(gè)參數(shù)是請(qǐng)求成功后的 響應(yīng)體

superagent.get(hotSearchURL, (err, res) => {if (err) console.error(err); });

網(wǎng)頁元素分析

打開目標(biāo)站對(duì)網(wǎng)頁中的 DOM 元素進(jìn)行一波分析。

對(duì) jQuery 比較熟的小老弟,看到下圖如此簡潔清晰明了的 DOM 結(jié)構(gòu),是不是有 N 種取出它每個(gè) tr 中的數(shù)據(jù)并 push 到一個(gè) Array 里的方法呢?

對(duì)!我們最終的目的就是要通過 jQuery 的語法,遍歷每個(gè) tr ,并將其每一項(xiàng)的 熱搜地址 、熱搜內(nèi)容 、 熱度值 、序號(hào) 、表情等信息 push 進(jìn)一個(gè)空數(shù)組中
再將它通過 nodejs 的 fs 模塊,寫入一個(gè) json 文件中。

jQuery 遍歷拿出數(shù)據(jù)

使用 jQuery 的 each 方法,對(duì) tbody 中的每一項(xiàng) tr 進(jìn)行遍歷,回調(diào)參數(shù)中第一個(gè)參數(shù)為遍歷的下標(biāo) index,第二個(gè)參數(shù)為當(dāng)前遍歷的元素,一般 $(this) 指向的就是當(dāng)前遍歷的元素。

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 包裝請(qǐng)求后的響應(yīng)體

在 nodejs 中,要想向上面那樣愉快的寫 jQuery 語法,還得將請(qǐng)求成功后返回的響應(yīng)體,用 cheerio 的 load 方法進(jìn)行包裝。

const $ = cheerio.load(res.text);

寫入 json 文件

接著使用 nodejs 的 fs 模塊,將創(chuàng)建好的數(shù)組轉(zhuǎn)成 json字符串,最后寫入當(dāng)前文件目錄下的 hotSearch.json 文件中(無此文件則會(huì)自動(dòng)創(chuàng)建)。

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,可看到根目錄下多了個(gè) hotSearch.json 文件。

定時(shí)爬取

雖然代碼可以運(yùn)行,也能爬取到數(shù)據(jù)并存入 json 文件。

但是,每次都要手動(dòng)運(yùn)行,才能爬取到當(dāng)前時(shí)間段的熱搜數(shù)據(jù),這一點(diǎn)都 不人性化!

最近微博熱搜瓜這么多,咱可是一秒鐘可都不能耽擱。我們最開始期望的是每隔多長時(shí)間 定時(shí)執(zhí)行爬取 操作。瓜可不能停!


接下來,對(duì)代碼進(jìn)行 小部分改造。

數(shù)據(jù)請(qǐng)求封裝

由于 superagent 請(qǐng)求是個(gè)異步方法,我們可以將整個(gè)請(qǐng)求方法用 Promise 封裝起來,然后 每隔指定時(shí)間 調(diào)用此方法即可。

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 詳解

定時(shí)任務(wù)我們可以使用 node-schedule 這個(gè) nodejs庫 來完成。
https://github.com/node-schedule/node-schedule

先安裝

npm i node-schedule -D

頭部引入

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

用法(每分鐘的第 30 秒定時(shí)執(zhí)行一次):

const rule = "30 * * * * *"; schedule.scheduleJob(rule, () => {console.log(new Date()); });

規(guī)則參數(shù):

* * * * * * ┬ ┬ ┬ ┬ ┬ ┬ │ │ │ │ │ │ │ │ │ │ │ └ 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 個(gè)占位符從左到右依次代表:秒、分、時(shí)、日、月、周幾
* 表示通配符,匹配任意。當(dāng) * 為秒時(shí),表示任意秒都會(huì)觸發(fā),其他類推。
來看一個(gè) 每小時(shí)的第20分鐘20秒 定時(shí)執(zhí)行的規(guī)則:

20 20 * * * *

更多規(guī)則自行搭配。

定時(shí)爬取,寫入文件

使用定時(shí)任務(wù)來執(zhí)行上面的請(qǐng)求數(shù)據(jù),寫入文件操作:

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);} });

哦對(duì),別忘了 捕獲異常

下面貼上完整代碼(可直接 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);} });

各種玩法

  • 以上代碼可直接集成進(jìn)現(xiàn)有的 express koa eggjs 或者原生的 nodejs 項(xiàng)目中,作為接口返回給前端。

  • 集成進(jìn) Serverless,作為接口返回給前端。

  • 對(duì)接微信公眾號(hào),發(fā)送 熱搜 關(guān)鍵字即可實(shí)時(shí)獲取熱搜數(shù)據(jù)。

  • 集成進(jìn) 微信機(jī)器人 ,每天在指定的時(shí)間給自己/群里發(fā)送微博熱搜數(shù)據(jù)。

  • other…

程序員導(dǎo)航站:https://iiter.cn

  • 看到這里啦,點(diǎn)個(gè) 在看 支持一下吧。
  • 關(guān)注公眾號(hào) 前端糖果屋 互相學(xué)習(xí)鴨。
  • 添加微信 uumovies ,拉你進(jìn) 技術(shù)交流群 探討人生。
  • 代碼 github 已開源:

    https://github.com/isnl/weibo-hotSearch-crawler

    總結(jié)

    以上是生活随笔為你收集整理的nodejs实现定时爬取微博热搜的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。