Skip to content

抖音

下载表情包

有时候需要将抖音的表情包弄去wx,vivo手机是可以直接拖过去的,但是别的手机咋整?请看下文

将所有要的表情包发给一个朋友,当中聊天记录,打开F12往上滚,确保你要的表情包都被渲染出来。然后执行以下代码。可以得到一个变量imgSrcs ,这个是所有表情包的url地址(目前是这样,如果抖音不改就是可以这样执行的)

js
const imgSrcs = Array.from(document.querySelectorAll('.j1fggzIT img'))
  .map(img => img.src);

目前这些地址都是GIF格式,然后替换一下js文件中的imgSrcs变量,然后执行js文件,就可以下载所有的表情包了。(AI是个好东西,这种node脚本都不用自己写了)

查看代码
js
/**
 * 批量下载图片
 * */
const fs = require('fs');
const path = require('path');
const axios = require('axios');

// ==================== 你只需要改这一部分 ====================
const imgSrcs = [
  'https://p3-sign.douyinpic.com/obj/tos-cn-o-0812/owTAv8A9igqBPyyFBICwa86iEAnMvrYuPgIAs?lk3s=9698d6d2&x-expires=1788076800&x-signature=ThYEhMnRL5zf1N8cwqi03SN48AE%3D&from=2526598866&s=im_2&se=false&sc=image&biz_tag=aweme_im&l=20250830161929BB3ACE93FBCDE06B3626',
  'https://p3-sign.douyinpic.com/obj/tos-cn-o-0812/oQ4tqC9iAGY0AIUErBi0AnCBQ9GTAgptfsVZB6?lk3s=9698d6d2&x-expires=1788076800&x-signature=D0YFmJxLC6%2B1TP8yFYa5bU7tYkM%3D&from=2526598866&s=im_2&se=false&sc=image&biz_tag=aweme_im&l=2025083016192366EB1435F28EB10ABFA2',
  'https://p3-sign.douyinpic.com/obj/tos-cn-o-0812/oQfXhXiIAijnAQHIhELRBaFGAUaJABfKe2Vl0h?lk3s=9698d6d2&x-expires=1788076800&x-signature=vcADRFYDTlWNEmhwc46aXLnDMaw%3D&from=2526598866&s=im_2&se=false&sc=image&biz_tag=aweme_im&l=20250830161920D82F22DF7DEF8A8F1961',
  'https://p3-sign.douyinpic.com/obj/tos-cn-o-0812/oYbBAWBfBzc0iAA7EiQuYc3BQi2ZBNAFoXOtIA?lk3s=9698d6d2&x-expires=1788076800&x-signature=XcxfowaDoEmzdczZkB5UMfqjoIU%3D&from=2526598866&s=im_2&se=false&sc=image&biz_tag=aweme_im&l=202508301619182E4FBFE5209CAB6BC712',
  'https://p3-sign.douyinpic.com/obj/tos-cn-o-0812/oEAlAeKnGCEiLAeLFYIlSgIeMIIQ7muA5KGZfD?lk3s=9698d6d2&x-expires=1788076800&x-signature=wO6dRwWTlZnHedHZNpGFnmvYD1Q%3D&from=2526598866&s=im_2&se=false&sc=image&biz_tag=aweme_im&l=20250830161915BB3ACE93FBCDE06B312F',
  'https://p3-sign.douyinpic.com/obj/tos-cn-o-0812/o0TIFfFPAD8pWNrIS6FFggQExA90A5ufyACoAH?lk3s=9698d6d2&x-expires=1788076800&x-signature=WxAk9Yt5w8LnTHVM%2BspTcNxMiis%3D&from=2526598866&s=im_2&se=false&sc=image&biz_tag=aweme_im&l=20250830161912EE907671D0FDAA8B5077',
  'https://p3-sign.douyinpic.com/obj/tos-cn-o-0812/oYAAyidiUWGkBaVAYfBBTXZzQGi1gCAIS0zJEw?lk3s=9698d6d2&x-expires=1788076800&x-signature=YQlGOfcooqoO%2FXA2vFncy7vwoC4%3D&from=2526598866&s=im_2&se=false&sc=image&biz_tag=aweme_im&l=20250830161909AD6FD9C1AEDBB5817D52',
  'https://p3-sign.douyinpic.com/obj/tos-cn-o-0812/oI6ALsCi5mBGEj2A4aAAgr4BZhAviIg9SkIvM?lk3s=9698d6d2&x-expires=1788001200&x-signature=nLNLwpF1%2B2V62cVEwaCrZE%2FdPkk%3D&from=2526598866&s=im_2&se=false&sc=image&biz_tag=aweme_im&l=021756466741195fdbddc060003014a0000000000000016470dee'
];
// ===========================================================

// 下载目录
const downloadDir = './downloads';
if (!fs.existsSync(downloadDir)) {
  fs.mkdirSync(downloadDir);
}

// 生成基于当天的文件名,如 08301.gif
function generateFilename(index) {
  const now = new Date();
  const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始
  const day = String(now.getDate()).padStart(2, '0');
  return `${month}${day}${index}.gif`;
}

// 获取当天已存在的 gif 文件数量,避免重名
function getNextIndex() {
  const now = new Date();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  const todayPrefix = `${month}${day}`;

  // 读取目录中已有的 todayPrefix 开头的 .gif 文件
  let maxIndex = 0;
  if (fs.existsSync(downloadDir)) {
    const files = fs.readdirSync(downloadDir);
    files.forEach(file => {
      const match = file.match(new RegExp(`^${todayPrefix}(\\d+)\\.gif$`));
      if (match) {
        const num = parseInt(match[1], 10);
        if (num > maxIndex) maxIndex = num;
      }
    });
  }
  return maxIndex + 1; // 下一个可用编号
}

// 下载单个图片
async function downloadImage(url, index) {
  try {
    const filename = generateFilename(index);
    const filepath = path.join(downloadDir, filename);

    const response = await axios({
      method: 'GET',
      url: url,
      responseType: 'stream',
      timeout: 10000 // 10秒超时
    });

    const writer = fs.createWriteStream(filepath);
    response.data.pipe(writer);

    return new Promise((resolve, reject) => {
      writer.on('finish', () => {
        console.log(`✅ 下载完成: ${filename}`);
        resolve();
      });
      writer.on('error', (err) => {
        console.error(`❌ 写入失败: ${filename}`, err.message);
        fs.unlinkSync(filepath); // 删除残缺文件
        reject(err);
      });
      response.data.on('error', (err) => {
        console.error(`❌ 下载流错误: ${url}`, err.message);
        reject(err);
      });
    });
  } catch (error) {
    console.error(`❌ 下载失败: ${url}`, error.message);
  }
}

// 批量下载主函数
async function downloadAll() {
  console.log('开始下载图片...');

  const startIndex = getNextIndex();

  for (let i = 0; i < imgSrcs.length; i++) {
    const url = imgSrcs[i];
    if (!url) continue;

    const fileIndex = startIndex + i;
    await downloadImage(url, fileIndex);

    // 每次下载间隔 300ms,避免请求太密集
    await new Promise(resolve => setTimeout(resolve, 300));
  }

  console.log('🎉 所有图片下载完成!');
  console.log(`📁 文件保存在: ${path.resolve(downloadDir)}`);
}

// 执行
downloadAll();

By Modify.