[JS真好玩] 用JS找到: 哪 个 小 坏 蛋 给 我 连 点 2 次 赞 ?

·  阅读 12656
[JS真好玩] 用JS找到: 哪 个 小 坏 蛋 给 我 连 点 2 次 赞 ?

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

这是我的专栏《JS真好玩》,将教你用JS实现一些有趣的东西。JS可以直接在浏览器运行,可以很方便的跟我学习用JS做好玩儿的事情。感谢大家关注~文章求赞噢!祝大家早日变成一名「前端极客」!

背景

上篇文章,我们轻松就找到了每天是谁取关了创作者,参考《掘金创作者必备: 监控每天是谁取关了你?》

但是知道是谁取关了创作者,只是好玩儿。创作者更想知道的是:

天天是谁在欺骗我的感情?有人给文章点了赞,系统给我推送了点赞消息,我欣喜若狂。结果小坏蛋又点了一次赞,把点赞给取消了!

掘金的产品形态

这件事情是很难知道的,掘金并没有把取消赞这件事情推送给我们!掘金是这样的:

用户点赞了,系统就给你推送他赞了你。后续他再给你取消(包括赞后立马点取消、或者过几天再点取消),系统都不会给你发推送,之前的推送也不会撤回。哪怕他再给点重新点了赞,系统也不会再发任何推送了。

我的解法

但是我,找到了解法!

现在,我们可以用JS找到:是哪个小坏蛋给创作者连续点了2次赞了!

关键点:

  1. 系统推送点赞消息会一直保留。所以其他人赞过的证据,一直在系统推送里。
  2. 每个用户点赞后的记录,也会在他个人主页。比如这是我赞过的文章:juejin.cn/user/615367…。如果用户取消赞,这里的记录会消失!

只要针对这两项做diff,就知道,是哪个小坏蛋点赞又取消了!

上代码

注意代码第一行!要改成你自己的uuid噢!如何找到自己的uuid?随便打开掘金一个地址,比如本文地址:juejin.cn/post/711210…,按F12打开浏览器的开发者工具,刷新一下,看看fetch请求的参数,找到包含uuid的,那个字段,就是你的 uuid啦!

image.png

const UUID = ''; // 你的uuid,抓包获取,不是你个人主页网址中的ID
const AID = '2608'; // 固定值,可能与掘金版本号有关
const MAX_MESSAGE_PAGE = 1; // 最大搜索几页自己收到的点赞消息(建议1页即可)
const MAX_DIGG_PAGE = 2; // 最大搜索几页其他用户的所有点赞文章(建议最大2页即可,太多会很慢)

/** 不能给掘金太大压力,我们定义个sleep函数,1秒请求一次就好 */
const sleep = () => new Promise(resolve => setTimeout(resolve, 1000));

/** 通用的请求函数 */
const request = async (url, init) => {
  const res = await fetch(url, { headers: { "content-type": "application/json" }, "mode": "cors", "credentials": "include", ...init });
  const data = await res.json();
  if (data.err_no) throw data;
  return data;
};

/** 请求某用户赞文章列表 */
const requestInteract = (user_id, cursor) => request(`https://api.juejin.cn/interact_api/v1/digg/query_page?aid=${AID}&uuid=${UUID}}`, {
  "body": JSON.stringify({ cursor, user_id, item_type: 2, sort_type: 2 }),
  "method": "POST",
});

/** 请求点赞消息列表 */
const requestMessage = (cursor) => request(`https://api.juejin.cn/interact_api/v1/message/get_message?aid=${AID}&uuid=${UUID}`, {
  "body": JSON.stringify({ message_type: 1, cursor, limit: 20, aid: AID }),
  "method": "POST",
});


let cursor = '0';
const user_article_array = [];
// 获取自己文章被点赞的「用户-文章」列表
for (let i = 0; i < MAX_MESSAGE_PAGE; i++) {
  const data = await requestMessage(cursor);
  cursor = data.cursor;
  const messages = data.data;
  if (!messages) break;
  user_article_array.push(...messages.filter(message => message.dst_info.id_type === 2));
  if (messages.length < 20) break;
  await sleep();
}

// 遍历「用户-文章」列表,计算所有用户的点赞文章列表,存到users里
const users = {};
const bad_users = [];
for (const user_article of user_article_array) {
  let cursor = '0';
  const user_id = user_article.src_info.item_id;
  // 如果user_id没有被获取过,就获取一下他的点赞文章列表。否则直接用之前的结果
  if (!(user_id in users)) {
    const articles_digged_by_user = [];
    for (let i = 0; i < MAX_DIGG_PAGE; i++) {
      const data = await requestInteract(user_id, cursor);
      cursor = data.cursor;
      const diggs = data.data;
      if (!diggs) break;
      articles_digged_by_user.push(...diggs.map(digg => digg.article_id));
      if (diggs.length < 10) break;
      await sleep();
    }
    users[user_id] = articles_digged_by_user;
  }
  const article = user_article.dst_info.item_id;
  const article_name = user_article.dst_info.name;
  const user_name = user_article.src_info.name;
  // 疑似找到一个小坏蛋
  if (!users[user_id].includes(article))  {
    const bad_user = { user_name: user_article.src_info.name, article_name: user_article.dst_info.name, user_id, article };
    console.log(bad_user);
    bad_users.push(bad_user);
  }
}
// 打印所有的疑似小坏蛋
console.log(bad_users);

注意,以上代码只能找到疑似小坏蛋。一些用户点赞很多,点的赞就被其他赞淹没啦~而我们的代码,为了不给掘金太大压力,每次只会读取用户最新点赞的20篇文章~

所以拿到结果后,需要针对这些嫌疑人做二次确认噢~

如何二次确认?你可以手动点开他的主页,看看他赞的文章有没有你的文章。或者像我一样,cool一点,用代码实现!这些代码逻辑就交给你啦!你可以的!我相信你看了我专栏这么多文章,一定也学会啦!关于如何抓包,可以在这里学:《遇到表格,手动翻页太麻烦?我教你写脚本,一页展示所有数据》。我在文中教学了如何使用浏览器Copy as fetch,学会后,你也可以用浏览器发请求啦。

写在最后

我是HullQin,独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋、UNO等游戏,绝不收费,绝无广告,点这就能开始玩。还独立开发了《合成大西瓜重制版》。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享:《教你做小游戏》《极致用户体验》

分类:
前端
分类:
前端
收藏成功!
已添加到「」, 点击更改