Logo

Node爬取微博、知乎热点

avatar Charlie 16 Jul 2024

微博和知乎作为国内两大吃瓜平台,每天的热点不断,辐射不同领域,对我们粗略了解当前社会可谓是方便快捷,然而手机app中广告太多,稍不注意就帮我买东西,实在是烦人,于是我采用技术手段来获取我所需要的(只吃瓜,不评论)。

必要工具

  • cheerio
  • superagent

Superagent

它是一个灵活的Node.js HTTP请求库,支持Promise API,使得从URL获取内容变得轻而易举。由于微博和知乎的热点页面不是单页面应用(SPA),使用Superagent可以轻松地获取HTML文本,成为我们探索的第一步。

Cheerio

获取HTML文本后,Cheerio便是我们解析这堆文本的利器。它提供了类似于jQuery的语法,使得操作DOM成为一种享受,帮我们轻松筛选和获取所需数据。

目标网站

我们需要从微博、知乎站点获取cookie,这样爬虫才能获取到数据,微博不需要登录就可以拿到,知乎需要登录。

分析网站结构

首先我们看看微博的结构,如下图

微博

可以看到以class td-02就是我们需要的节点,其包括了热点话题名称、讨论数量,td-01、td-03对我来说不太需要就不处理。

接下来我们看知乎的分析,知乎比微博稍微复杂点,内容也多一些。

知乎

可以看到class HotItem就是每一个热点的容器,其下面后标题、简介、热度、配图。

准备工作

  • pnpm init
  • pnpm install cheerio superagent lodash

具体代码

weibo.js

const cheerio = require('cheerio');
const superagent = require('superagent');
const _ = require('lodash');

class Weibo {
  async initProcess() {
    const url = 'https://s.weibo.com/top/summary';
    const cookie = '请自行复制后粘贴';
    const html = await this.getRawHtml(url, cookie);
    const hotInfo = this.getHotInfo(html);
    console.log(hotInfo);
  }

  async getRawHtml(url, cookie) {
    const request = superagent.get(url);
    request.set('cookie', cookie);
    const data = await request;
    return data.text;
  }

  getHotInfo(html) {
    const $ = cheerio.load(html);
    const hotKeyElements = $('.td-02');
    const hotKeys = [];
    // 去重
    const tmpTitles = [];
    hotKeyElements.map((index, element) => {
      const a = $(element).find('a');
      const title = a.text();
      const span = $(element).find('span');
      // 默认top为999999999
      let count = 999999999;
      if (index) {
        count = parseInt(span.text(), 10);
      }
      if (tmpTitles.includes(title)) {
        return '';
      }
      tmpTitles.push(title);
      hotKeys.push({ title, count });
      return '';
    });
    return _.uniqBy(hotKeys.filter(item => item.title && !_.isNaN(item.count)), 'title');
  }
}

const weibo = new Weibo();
weibo.initProcess();
zhihu.js

const cheerio = require('cheerio');
const superagent = require('superagent');
const _ = require('lodash');

class Zhihu {
  async initProcess() {
    const url = 'https://www.zhihu.com/hot';
    const cookie = '请自行复制后粘贴';
    const html = await this.getRawHtml(url, cookie);
    const hotInfo = this.getHotInfo(html);
    console.log(hotInfo);
  }

  async getRawHtml(url, cookie) {
    const request = superagent.get(url);
    request.set('cookie', cookie);
    const data = await request;
    return data.text;
  }

  getHotInfo(html) {
    const $ = cheerio.load(html);
    const hotItemElements = $('.HotItem');
    const hotKeys = [];
    hotItemElements.map((index, element) => {
      const title = $(element).find('.HotItem-title').text();
      const img = $(element).find('.HotItem-img img').attr('src');
      const hot = $(element).find('.HotItem-metrics--bottom').text() || $(element).find('.HotItem-metrics').text();
      const url = $(element).find('.HotItem-content > a').attr('href') || '';
      const question_id = parseInt(url.split('/').pop() || '', 10);
      if (question_id) {
        hotKeys.push({
          title,
          img: img || '',
          url: url || '',
          hot: parseInt(hot, 10),
          question_id: String(question_id),
        });
      }
      return '';
    });
    return _.uniqBy(hotKeys.filter(item => item.question_id && !_.isNaN(item.hot)), 'question_id');
  }
}

const zhihu = new Zhihu();
zhihu.initProcess();

运行结果如下

微博热点

知乎热点

自行扩展

实施上述方案后,我们得以迅速掌握微博与知乎的热点动态,筛选出有价值的信息。而这一切,只是冰山一角。在获取了这些珍贵数据之后,接下来可以考虑运用node-schedule等工具定时爬取最新内容,并将其存储、分析,抑或是以网站形式呈现,甚至进行高级的热词分析等,皆看各位的创意发挥了。

Tags
爬虫
Node
微博
知乎
联系我们