微信文章页面中显示下载按钮并列出音频链接(可复制),兼容动态渲染音频标签的情况。
// ==UserScript==
// @name 公众号音频下载(稳定修复版)
// @namespace http://tampermonkey.net/
// @version 1.3.3
// @description 微信文章页面中显示下载按钮并列出音频链接(可复制),兼容动态渲染音频标签的情况。
// @author bingo8670 + ChatGPT
// @match https://mp.weixin.qq.com/s*
// @grant GM_download
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const collectedItems = new Map(); // 使用 Map 防止重复插入
let urlPanelInitialized = false;
function getVoiceElements() {
return document.querySelectorAll('mp-common-mpaudio, mpvoice, mp-audio, .mp_common_audio');
}
function extractVoiceInfo(el) {
const fileid = el.getAttribute('voice_encode_fileid');
const title = el.getAttribute('name') || '音频';
if (!fileid) return null;
const url = 'https://res.wx.qq.com/voice/getvoice?mediaid=' + fileid;
return { url, title };
}
function addDownloadButton(el, info) {
if (el.dataset.downloadButtonInjected) return;
el.dataset.downloadButtonInjected = "true";
collectedItems.set(info.url, info.title); // 添加到链接集合
const btn = document.createElement('div');
btn.style = `
display:inline-block;
margin-top:10px;
padding:8px 12px;
background:#4CAF50;
color:#fff;
font-size:13px;
text-align:center;
border-radius:5px;
cursor:pointer;
`;
btn.innerHTML = '下载音频 “' + info.title + '”';
btn.onclick = function () {
try {
GM_download({
url: info.url,
name: info.title + '.mp3',
saveAs: true
});
} catch (e) {
console.error("下载失败:", e);
}
};
el.after(btn);
updateUrlDisplayArea(); // 每次添加后刷新底部输出
}
function createUrlDisplayArea() {
if (urlPanelInitialized) return;
urlPanelInitialized = true;
const panel = document.createElement('div');
panel.id = 'audio-url-display';
panel.style = `
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #f9f9f9;
border-top: 2px solid #ccc;
padding: 10px;
font-size: 13px;
max-height: 200px;
overflow-y: auto;
z-index: 9999;
`;
const title = document.createElement('div');
title.innerHTML = '<b>📥 可复制音频链接:</b>';
panel.appendChild(title);
const container = document.createElement('div');
container.id = 'audio-url-list';
container.style = `display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px;`;
panel.appendChild(container);
document.body.appendChild(panel);
}
function updateUrlDisplayArea() {
if (!urlPanelInitialized) createUrlDisplayArea();
const container = document.getElementById('audio-url-list');
if (!container) return;
container.innerHTML = ''; // 清空
collectedItems.forEach((title, url) => {
const linkDiv = document.createElement('div');
linkDiv.textContent = `《${title}》 ${url}`;
linkDiv.title = title;
linkDiv.style = `
display:inline-block;
background:#4CAF50;
color:#fff;
padding:6px 10px;
border-radius:5px;
font-size:12px;
cursor:text;
user-select:text;
`;
container.appendChild(linkDiv);
});
}
// 每当 DOM 中插入新节点,就检查是否有音频标签
const observer = new MutationObserver(() => {
const els = getVoiceElements();
els.forEach(el => {
const info = extractVoiceInfo(el);
if (info) addDownloadButton(el, info);
});
});
// 页面加载完开始监听 DOM 变化
window.addEventListener('load', () => {
observer.observe(document.body, {
childList: true,
subtree: true
});
// 初次手动触发一次
const els = getVoiceElements();
els.forEach(el => {
const info = extractVoiceInfo(el);
if (info) addDownloadButton(el, info);
});
});
})();