野口笑子 发表于 2026-1-10 23:21:11

找ai搓了个油猴脚本,方便在nyaa搜动画时切换不同译名作为关键词

脚本会根据当前搜索框内容查询并列出相关动画的各种名称,在列表中点击条目可以直接进行搜索,点击条目前的语言标识可以替换搜索框内容



查询服务部署在cloudflare workers上,数据用的是anidb提供的离线名称库,要自建的话可以按下面的步骤
1. 新建KV
2. 新建Workers并贴入代码
3. 绑定Workers和KV,变量名称填“ANIME_TITLES”
4. 添加“变量和机密”用作数据更新页面的密码,类型选“密钥”,变量名称填“PASSWORD”,值为要设置的密码

部署完成后,替换油猴中两处域名即可。首次查询会自动从anidb下载数据,后续如果需要更新数据可以自行添加定时任务或者直接打开workers地址手动更新。anidb提供的数据是每日更新,定时间隔也应当不小于一天。


static/image/hrline/line3.png


油猴脚本:
// ==UserScript==
// @Name         Nyaa 搜索建议(动画别名)
// @namespace    http://localhost/
// @version      1.1
// @description在 Nyaa 页面快捷查询动画译名,方便切换关键词进行搜索
// @author       Claude & Gemini
// @match      *://*.nyaa.si/*
// @grant      GM_xmlhttpRequest
// @connect      anime.titles.workers.dev
// ==/UserScript==

(function () {
    'use strict';

    const style = document.createElement('style');
    style.textContent = `
      #anime-search-btn {
            background: #337ab7;
            color: #fff;
            border: none;
            border-radius: 3px;
            margin-left: 5px;
      }
      #anime-search-btn:hover { background: #286090; }

      #anime-panel {
            position: absolute;
            z-index: 99999;
            background: #fff;
            border-radius: 3px;
            padding: 10px;
            width: 300px;
            max-width: 90vw;
            max-height: 70vh;
            overflow-y: auto;
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            display: none;
            font-size: 14px;
      }
      #anime-panel.show { display: block; }

      #anime-panel-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 10px;
            padding-bottom: 8px;
            border-bottom: 1px solid #eee;
      }
      #anime-panel-header span { color: #595959; font-size: 12px; }
      #anime-close { cursor: pointer; font-size: 18px; color: #999; }
      #anime-close:hover { color: #333; }

      .anime-item {
            margin-bottom: 5px;
            padding-bottom: 5px;
            border-bottom: 1px solid #eee;
      }
      .anime-item:last-child { border-bottom: none; margin-bottom: 0; }
      .anime-aid { color: #707070; font-size: 11px; margin-bottom: 4px; text-decoration: none; }
      .anime-aid:hover { text-decoration: underline; }
      .anime-titles { padding-left: 0; margin: 0; list-style: none; }
      .anime-titles li { margin: 2px 0; }
      .anime-titles a {
            color: #337ab7;
            text-decoration: none;
      }
      .anime-titles a:hover { text-decoration: underline; }
      .anime-titles .lang {
            color: #707070;
            font-size: 11px;
            margin: 5px 5px;
            cursor: pointer;
            user-select: none;
            transition: color 0.2s;
      }
      .anime-titles .lang:hover {
            color: #000;
            /* font-weight: bold;*/
      }

    `;
    document.head.appendChild(style);

    function showError(msg) {
      panel.classList.add('show');
      document.getElementById('anime-info').textContent = msg;
      document.getElementById('anime-content').innerHTML = '';
    }

    // 搜索按钮
    const btn = document.createElement('button');
    btn.id = 'anime-search-btn';
    btn.className = 'btn btn-default';
    btn.type = 'button';

    // 创建 Font Awesome 图标
    const icon = document.createElement('i');
    icon.className = 'fa fa-info-circle fa-paw';
    btn.appendChild(icon);

    // 修改插入逻辑
    function insertBtn() {
      const target = document.querySelector('.search-btn');
      if (target) {
            // 创建一个符合 Bootstrap input-group 规范的包装器
            const wrapper = document.createElement('div');
            wrapper.className = 'input-group-btn';
            // 将按钮放入包装器
            wrapper.appendChild(btn);
            // 将包装器插入到搜索按钮组的后面
            target.insertAdjacentElement('afterend', wrapper);
      } else {
            // 兜底方案
            btn.style.cssText = 'position:fixed;top:80px;right:20px;z-index:99999;';
            document.body.appendChild(btn);
      }
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', insertBtn);
    } else {
      insertBtn();
    }

    // 结果面板
    const panel = document.createElement('div');
    panel.id = 'anime-panel';
    panel.innerHTML = `
      <div id="anime-panel-header">
            <span id="anime-info"></span>
            <span id="anime-close">X</span>
      </div>
      <div id="anime-content"></div>
    `;
    document.body.appendChild(panel);

    panel.querySelector('#anime-close').onclick = () => panel.classList.remove('show');

    // 点击语言标签替换输入框内容
    panel.addEventListener('click', function(e) {
      // 检查点击的是不是 class="lang" 的元素
      if (e.target.classList.contains('lang')) {
            const title = e.target.getAttribute('data-title');
            const input = document.querySelector('.search-bar');

            if (title && input) {
                input.value = title; // 替换内容
                input.focus(); // 让输入框获得焦点

                // 视觉反馈,闪烁输入框背景
                const originalBg = input.style.backgroundColor;
                input.style.backgroundColor = '#88b5dd';
                setTimeout(() => {
                  input.style.backgroundColor = originalBg;
                }, 200);
            }
      }
    });

    const langMap = { 'ja': '日', 'en': '英', 'zh-Hans': '简', 'zh-Hant': '繁', 'x-jat': '罗' };

    btn.onclick = (e) => {
      e.preventDefault();
      e.stopPropagation();

      const input = document.querySelector('.search-bar');
      if (!input) return;

      const rect = btn.getBoundingClientRect();
      const scrollY = window.scrollY || document.documentElement.scrollTop;
      const docWidth = document.documentElement.clientWidth;

      // 设置面板坐标
      panel.style.top = (rect.bottom + scrollY + 5) + 'px';
      panel.style.left = 'auto'; // 清除可能存在的左定位
      panel.style.right = (docWidth - rect.right) + 'px'; // 右对齐

      // 检查关键字
      const keyword = input.value.trim();

      if (!keyword) {
            showError('请输入关键字');
            return;
      }

      // 有关键字,开始搜索流程
      panel.classList.add('show');
      const content = document.getElementById('anime-content');
      const info = document.getElementById('anime-info');

      content.innerHTML = '搜索中...';
      info.textContent = '';

      // 发起请求
      GM_xmlhttpRequest({
            method: 'GET',
            url: `https://anime.titles.workers.dev/?q=${encodeURIComponent(keyword)}&limit=50`,
            onload: function (res) {
                try {
                  const data = JSON.parse(res.responseText);
                  if (data.results && data.results.length > 0) {
                        info.textContent = `${data.count} 个结果`;//(${data.searchTime})
                        content.innerHTML = data.results.map(item => `
                            <div class="anime-item">
                              <a class="anime-aid" href="https://anidb.net/anime/${item.aid}" target="_blank">AID: ${item.aid}</a>
                              <ul class="anime-titles">
                                    ${item.titles.map(t => {
                                        // 处理标题中的双引号,防止破坏 HTML 结构
                                        const safeTitle = t.title.replace(/"/g, '&quot;');

                                        // 在 span 中添加 data-title 属性和 title 提示
                                        return `
                                        <li>
                                          <span class="lang" data-title="${safeTitle}" title="填入搜索框">
                                                [${langMap || t.language}]
                                          </span>
                                          <a href="/?f=0&c=0_0&q=${encodeURIComponent(t.title)}" target="_blank">${t.title}</a>
                                        </li>
                                        `;
                                    }).join('')}
                              </ul>
                            </div>
                        `).join('');
                  } else {
                        content.innerHTML = '未找到结果';
                  }
                } catch (e) {
                  content.innerHTML = '解析失败: ' + e.message;
                }
            },
            onerror: () => { content.innerHTML = '请求失败'; }
      });
    };
    document.addEventListener('click', function(e) {
      // 点击空白处关闭面板
      if (!panel.contains(e.target) && e.target !== btn) {
            panel.classList.remove('show');
      }
    });
})();



static/image/hrline/line3.png


Workers代码:
let cachedTitles = null;
let cacheTime = 0;
const CACHE_TTL = 300000; // 5分钟
const ANIDB_URL = 'http://anidb.net/api/anime-titles.dat.gz';

export default {
async fetch(request, env) {
    const url = new URL(request.url);

    // 优先处理搜索逻辑
    if (url.searchParams.has('q')) {
      return handleSearch(request, env, url);
    }

    // 不带 q 参数时进入管理
    return handleManagement(request, env, url);
},

// 定时任务处理
async scheduled(event, env, ctx) {
    console.log('开始定时更新任务。', new Date().toISOString());
    try {
      await autoImportData(env);
      console.log('定时更新完成');
    } catch (error) {
      console.error('定时更新失败!', error);
    }
}
};

// 搜索逻辑
async function handleSearch(request, env, url) {
const corsHeaders = {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type',
};

if (request.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
}

const query = url.searchParams.get('q');
const limit = parseInt(url.searchParams.get('limit') || '100');

try {
    const startTime = Date.now();
    const now = Date.now();

        // 缓存检查
        if (!cachedTitles || (now - cacheTime) > CACHE_TTL) {
          let allTitlesData;
          
          try {
                allTitlesData = await env.ANIME_TITLES.get('all_titles');
          } catch (error) {
                // KV 未绑定或访问失败
                return jsonResponse({
                  error: 'KV 存储未配置或访问失败',
                  detail: error.message,
                  hint: '请检查 ANIME_TITLES KV 命名空间是否已正确绑定'
                }, 503, corsHeaders);
          }
          
          if (!allTitlesData) {
                // 数据未初始化,自动导入
                console.log('检测到数据未初始化,开始自动导入……');
                try {
                  await autoImportData(env);
                  // 导入后重新获取数据
                  const newData = await env.ANIME_TITLES.get('all_titles');
                  cachedTitles = JSON.parse(newData);
                  cacheTime = now;
                } catch (error) {
                  return jsonResponse({
                        error: '数据未初始化且自动导入失败',
                        detail: error.message
                  }, 503, corsHeaders);
                }
          } else {
                cachedTitles = JSON.parse(allTitlesData);
                cacheTime = now;
          }
        }
   
    // 搜索逻辑
    const searchLower = query.toLowerCase();
   
    // 一次遍历完成搜索和聚合
    const results = Object.entries(cachedTitles)
      .filter(() => {
      // 检查该 AID 下是否有任何标题匹配
      return titles.some(t => t.title?.toLowerCase().includes(searchLower));
      })
      .slice(0, limit) // 限制数量
      .map(() => ({
      aid: parseInt(aid),
      titles: titles // 直接引用,无需重新构造
      }));
   
    return jsonResponse({
      query,
      count: results.length,
      searchTime: `${Date.now() - startTime}ms`,
      cached: cacheTime !== now,
      results
    }, 200, corsHeaders);

} catch (error) {
    return jsonResponse({ error: error.message }, 500, corsHeaders);
}
}

// 管理界面
const COOKIE_NAME = 'AniDB_Updater_Auth';

async function handleManagement(request, env, url) {
// 仅在进入管理逻辑时才解析 Cookie
const cookie = request.headers.get('Cookie');
const authCookie = cookie && cookie.match(new RegExp(`${COOKIE_NAME}=([^;]+)`));
const isLogged = (authCookie && authCookie === env.PASSWORD);

// 1. 登录处理
if (url.pathname === '/login' && request.method === 'POST') {
    const formData = await request.formData();
    if (formData.get('password') === env.PASSWORD) {
      const headers = new Headers();
      headers.append('Set-Cookie', `${COOKIE_NAME}=${env.PASSWORD}; Path=/; Max-Age=86400; HttpOnly; Secure; SameSite=Strict`);
      headers.append('Location', '/');
      return new Response(null, { status: 302, headers });
    }
    return new Response(null, { status: 302, headers: { 'Location': '/' } });
}

// 2. 一键导入处理
if (url.pathname === '/auto-import' && request.method === 'POST') {
    if (!isLogged) return new Response('Unauthorized', { status: 401 });
    try {
      const count = await autoImportData(env);
      return new Response(`自动导入完成,总条目数: ${count}`);
    } catch (e) {
      return new Response(`自动导入失败! ${e.message}`, { status: 500 });
    }
}

// 3. 手动上传处理
if (request.method === 'POST') {
    if (!isLogged) return new Response('Unauthorized', { status: 401 });
    try {
      const fileBuffer = await request.arrayBuffer();
      if (!fileBuffer || fileBuffer.byteLength === 0) return new Response('无文件内容', { status: 400 });
      
      const count = await processAndSaveData(fileBuffer, env);
      
      // 上传成功后,强制清空搜索缓存
      cachedTitles = null;
      
      return new Response(`更新完成,总条目数: ${count}`);
    } catch (e) {
      return new Response(`失败! ${e.message}`, { status: 500 });
    }
}

// 4. 页面渲染
const html = isLogged ? await renderUploadUI(env) : renderLoginUI();
return new Response(html, { headers: { 'Content-Type': 'text/html; charset=utf-8' } });
}

// ================= 自动导入功能 =================

async function autoImportData(env) {
// 检查上次更新日期
const metadata = await env.ANIME_TITLES.get('metadata');
if (metadata) {
    const meta = JSON.parse(metadata);
    const lastUpdate = new Date(meta.lastUpdate);
    const now = new Date();
   
    // 获取日期部分(忽略时间)
    const lastUpdateDate = lastUpdate.toISOString().split('T');
    const nowDate = now.toISOString().split('T');
   
    // 如果是同一天,拒绝更新
    if (lastUpdateDate === nowDate) {
      throw new Error(`今日已更新(${lastUpdate.toLocaleString('zh-CN')}),请明日再试`);
    }
}

console.log('正在从 AniDB 获取数据……');

// 从 AniDB 下载 .gz 文件,添加必要的请求头
const response = await fetch(ANIDB_URL, {
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:146.0) Gecko/20100101 Firefox/146.0',
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'Accept-Language': 'en-US,en;q=0.9',
      'Accept-Encoding': 'gzip, deflate, br, zstd',
      'Connection': 'keep-alive',
      'Host': 'anidb.net',
    },
    cf: {
      cacheTtl: 3600,
      cacheEverything: true
    }
});

if (!response.ok) {
    throw new Error(`下载失败! ${response.status} ${response.statusText}`);
}

const buffer = await response.arrayBuffer();
console.log(`下载完成,文件大小: ${buffer.byteLength} 字节`);

// 处理并保存数据
const count = await processAndSaveData(buffer, env);

// 清空缓存
cachedTitles = null;

console.log(`数据处理完成,总条目数: ${count}`);
return count;
}

// ================= 数据处理 (仅上传时调用) =================

async function processAndSaveData(buffer, env) {
const ALLOWED_LANGS = new Set(['ja', 'en', 'x-jat', 'zh-Hans', 'zh-Hant']);

// 定义语言优先级映射
const LANG_PRIORITY = {
    'zh-Hans': 1,
    'zh-Hant': 2,
    'ja': 3,
    'x-jat': 4,
    'en': 5
};

let text = '';
const view = new Uint8Array(buffer);

if (view === 0x1f && view === 0x8b) {
    try {
      const ds = new DecompressionStream('gzip');
      const stream = new Response(buffer).body.pipeThrough(ds);
      const decompressed = await new Response(stream).arrayBuffer();
      text = new TextDecoder('utf-8').decode(decompressed);
    } catch (e) { throw new Error('解压失败!'); }
} else {
    text = new TextDecoder('utf-8').decode(buffer);
}

const titles = [];
const lines = text.trim().split('\n');

for (const line of lines) {
    if (line.startsWith('#')) continue;
    const parts = line.split('|');
    if (parts.length !== 4) continue;
    const = parts;
    if (!aid || !title) continue;

    const type = parseInt(typeStr);
    if (type === 3) continue;

    if (ALLOWED_LANGS.has(language)) {
      titles.push({
      aid: parseInt(aid),
      type,
      language,
      title
      });
    }
}

if (titles.length === 0) throw new Error('无有效数据!');

// 按 AID 分组
const groupedByAid = {};
for (const item of titles) {
    const aid = item.aid.toString(); // 转为字符串作为 key
    if (!groupedByAid) {
      groupedByAid = [];
    }
    groupedByAid.push({
      type: item.type,
      language: item.language,
      title: item.title
    });
}

// 对每个 AID 的标题按语言优先级排序
for (const aid in groupedByAid) {
    groupedByAid.sort((a, b) => {
      const langA = LANG_PRIORITY || 99;
      const langB = LANG_PRIORITY || 99;
      return langA - langB;
    });
}

// 保存分组后的数据
await env.ANIME_TITLES.put('all_titles', JSON.stringify(groupedByAid));
await env.ANIME_TITLES.put('metadata', JSON.stringify({
    lastUpdate: new Date().toISOString(),
    totalTitles: titles.length,
    totalAnime: Object.keys(groupedByAid).length,
    source: 'auto'
}));

return titles.length;
}

// ================= 辅助函数 =================

function jsonResponse(data, status = 200, headers = {}) {
return new Response(JSON.stringify(data, null, 2), {
    status,
    headers: { ...headers, 'Content-Type': 'application/json; charset=utf-8' }
});
}

function renderLoginUI() {
return `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Login</title><style>body{display:flex;justify-content:center;align-items:center;height:100vh;margin:0;font-family:sans-serif;background:#fafafa}form{background:white;padding:2rem;border:1px solid #eaeaea;border-radius:2px;width:280px}input{width:100%;padding:10px;margin-bottom:10px;border:1px solid #ddd;border-radius:2px;box-sizing:border-box;outline:none}input:focus{border-color:#000}button{width:100%;padding:10px;background:#000;color:white;border:none;border-radius:2px;cursor:pointer;font-weight:bold}button:hover{opacity:0.8}.link-area{margin-bottom:15px;text-align:center;font-size:12px;word-break:break-all;}.link-area a{color:#555;}</style></head><body><form action="/login" method="POST"><div class="link-area"><a href="/?q=maruko&limit=50">Example</a></div><input type="password" name="password" placeholder="Password" required autofocus><button type="submit">Enter</button></form></body></html>`;
}

async function renderUploadUI(env) {
// 获取上次更新信息
let lastUpdateInfo = '';
try {
    const metadata = await env.ANIME_TITLES.get('metadata');
    if (metadata) {
      const meta = JSON.parse(metadata);
      const updateDate = new Date(meta.lastUpdate);
      lastUpdateInfo = `<div class="info-box">上次更新: ${updateDate.toLocaleString('zh-CN')} | 总条目: ${meta.totalTitles.toLocaleString()}</div>`;
    }
} catch (e) {
    lastUpdateInfo = '<div class="info-box">暂无更新记录</div>';
}

return `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>导入数据</title><style>body{font-family:sans-serif;max-width:500px;margin:3rem auto;padding:0 1rem;color:#333}.card{border:1px solid #eaeaea;padding:1.5rem;border-radius:2px;background:#fff;margin-bottom:1rem}h3{margin-top:0;font-size:1.1rem;margin-bottom:1rem}.info-box{background:#f5f5f5;padding:10px;border-radius:2px;font-size:13px;color:#666;margin-bottom:1rem}.upload-area{position:relative;height:120px;border:2px dashed #ddd;border-radius:2px;background:#fafafa;display:flex;align-items:center;justify-content:center;text-align:center;transition:border-color 0.2s;margin-bottom:1rem}.upload-area:hover{border-color:#999}.upload-area input{position:absolute;width:100%;height:100%;top:0;left:0;opacity:0;cursor:pointer;z-index:2}.placeholder{pointer-events:none;color:#666;font-size:0.9rem}button{background:#000;color:white;border:none;padding:12px;border-radius:2px;cursor:pointer;width:100%;font-weight:bold;margin-bottom:8px}button:disabled{background:#ccc;cursor:not-allowed}button:hover:not(:disabled){opacity:0.8}#log{margin-top:15px;font-size:13px;color:#555;word-break:break-all}.links{font-size:12px;margin-bottom:1rem;color:#888}.links a{color:#555}.divider{border-top:1px solid #eaeaea;margin:1.5rem 0;position:relative}.divider span{position:absolute;top:-10px;left:50%;transform:translateX(-50%);background:white;padding:0 10px;color:#999;font-size:12px}</style></head><body><div class="card"><h3>数据状态</h3>${lastUpdateInfo}</div><div class="card"><h3>一键导入</h3><div class="links">从 AniDB 自动获取最新数据</div><button class="btn-auto" onclick="autoImport()">一键导入最新数据</button><div class="divider"><span>或</span></div><h3>手动上传</h3><div class="links">手动下载:<a href="http://anidb.net/api/anime-titles.dat.gz" target="_blank">anidb.net/api/anime-titles.dat.gz</a></div><div class="upload-area"><input type="file" id="f" accept=".gz,.dat"><div class="placeholder" id="p">点击或拖拽文件 (.gz)</div></div><button onclick="u()">开始上传</button><div id="l"></div></div><script>document.getElementById('f').onchange=e=>{document.getElementById('p').innerHTML='已选择:<br><b>'+(e.target.files?e.target.files.name:'...')+'</b>'};async function autoImport(){const l=document.getElementById('l'),btns=document.querySelectorAll('button');btns.forEach(b=>b.disabled=1);l.innerText='正在从 AniDB 获取数据...';l.style.color='#0070f3';try{const r=await fetch('/auto-import',{method:'POST'});const t=await r.text();l.innerText=(r.ok?'成功!':'失败!')+t;l.style.color=r.ok?'#008000':'#d00';if(r.ok)setTimeout(()=>location.reload(),1500);if(r.status===401)location.reload()}catch(e){l.innerText='ERR: '+e;l.style.color='#d00'}finally{btns.forEach(b=>b.disabled=0)}}async function u(){const f=document.getElementById('f'),l=document.getElementById('l'),btns=document.querySelectorAll('button');if(!f.files.length)return alert('无文件');btns.forEach(b=>b.disabled=1);l.innerText='上传中...';l.style.color='#0070f3';try{const r=await fetch('/',{method:'POST',headers:{'Content-Type':'application/octet-stream'},body:f.files});const t=await r.text();l.innerText=(r.ok?'成功!':'失败!')+t;l.style.color=r.ok?'#008000':'#d00';if(r.ok)setTimeout(()=>location.reload(),1500);if(r.status===401)location.reload()}catch(e){l.innerText='ERR: '+e;l.style.color='#d00'}finally{btns.forEach(b=>b.disabled=0)}}</script></body></html>`;
}



SAOKiller 发表于 2026-1-11 00:43:55

可以,是我想要的功能,之前就总是先去找动画的罗马文和日文是什么,才去nyaa上搜索,这个就省事多了

HanTaNiA 发表于 2026-1-11 01:19:16

好帖帮顶

waecy 发表于 2026-1-11 13:32:42

本帖最后由 waecy 于 2026-3-13 19:04 编辑

支持,现在用AI写游猴脚本,多加调教,试错反馈可以写成不少好用的功能
浏览次数统计/一键复制 / 一键批量打开 / 一键磁力导出 /一键BT文件下载/BT压缩包打包/表格导出…

以前还得花一天写样式,调试脚本,如今只要提需求就能写出来, 确实方便多了

先推荐个一键复制

NYAA复制磁力
https://greasyfork.org/zh-CN/scripts/530242


waecy 发表于 2026-1-11 13:57:35

本帖最后由 waecy 于 2026-1-11 14:01 编辑

经过多年测试, AniDB个人也常用找英文或罗马音, 但亲测不全, 实际上找番, 若要外网找到所有番名, 中/日/英的话,需多个搭配, 实际网友搜刮,也只能选其一, 目前没全部搜刮收藏的轮子

三大最全资讯
1. Bangumi (搭配脚本,也可以加载Anidb或MAL的罗马音和英文名,但不全) 主要中文名/日文名
2. AniDB 最常用之一
3. MAL 补充英文名, 一些特典,广播剧英文名啥的, 这里最全

大部分情况,三大网站汇总,就算挺全的,但若要更全的话

1.TMDB 经常搜刮的不陌生,不少中文译名和网友自己添加的罗马音和英文名   用作补齐
2.AS 其实大部分重复,论全不如以上, 但可以部分补充

其他的
ANN
豆瓣
百科
萌娘
维基
...

说实话用的情况反而少, 需要看详细人物介绍和来源倒可以看看, 但收藏番名用于收藏的话,倒没必要, 番名的中/日/英/罗 有以上基本汇总完毕

别的国家语言我这边用的少, 比如俄语啥的,有的松鼠党喜欢收藏各种原盘, 各种语言的也能去搜下,不过这种大部分也有英文名作为标题, 个人感觉除非是个人刚需的话, 否则没必要收藏名称

PS: 不排除终极强迫症,爱好把各国语言的番名也收藏就是了


这是本人写的一个番名去重汇总功能, 适合把不同番名汇总, 安装中文名[简体别名][繁体别名][日文名][英文名] 年份 集数 来收藏,需要的可自取
https://www.bilibili.com/video/BV1Lmn2z8E6P



✨番剧不同译名收藏-文本处理工具✨
https://anilistname.netlify.app/

页: [1]
查看完整版本: 找ai搓了个油猴脚本,方便在nyaa搜动画时切换不同译名作为关键词