Monknow是一款浏览器扩展,用作新标签页。但是官方没有提供数据导出的功能,导致我们收藏的很多网页没办法进行数据迁徙,这里我们自己动手通过js脚本导出数据。
使用说明(在Edge浏览器上测试通过):
- 打开MonKonw新标签页 :确保您看到的是MonKonw的标签页界面(需要登录自己的账户)
- 按F12打开开发者工具 :进入浏览器的调试模式
- 切换到控制台 :在开发者工具中找到并点击"控制台(Console)"选项卡
- 复制以下脚本 :将完整的脚本复制到剪贴板
- 粘贴并执行 :将脚本粘贴到控制台中,然后按Enter键执行
javascript
// MonKonw Chrome 扩展数据导出脚本
(function() {
console.log('=== MonKonw Chrome 扩展数据导出 ===');
console.log('执行时间:', new Date().toLocaleString());
console.log('当前页面:', window.location.href);
// 检查是否在扩展页面中
if (!window.location.href.startsWith('chrome-extension://')) {
console.error('错误:请在 MonKonw 扩展页面中执行此脚本!');
console.error('请打开新标签页,确保是 MonKonw 标签页,然后重新执行脚本。');
return;
}
// 1. 检查 chrome.storage API
console.log('\n1. 检查 Chrome 扩展存储 API...');
if (typeof chrome !== 'undefined' && chrome.storage) {
console.log('Chrome 扩展存储 API 可用');
// 读取所有存储数据
function readAllStorage() {
return new Promise((resolve) => {
const allData = {};
// 读取 local 存储
chrome.storage.local.get(null, (localData) => {
allData.local = localData;
// 读取 sync 存储
chrome.storage.sync.get(null, (syncData) => {
allData.sync = syncData;
// 读取 managed 存储(如果有)
chrome.storage.managed.get(null, (managedData) => {
allData.managed = managedData;
resolve(allData);
});
});
});
});
}
// 执行数据读取
readAllStorage().then((storageData) => {
console.log('\n2. 存储数据读取完成:');
console.log('local 存储项数量:', Object.keys(storageData.local).length);
console.log('sync 存储项数量:', Object.keys(storageData.sync).length);
console.log('managed 存储项数量:', Object.keys(storageData.managed).length);
// 显示存储数据的键名
console.log('\n存储数据键名:');
console.log('local 存储:', Object.keys(storageData.local));
console.log('sync 存储:', Object.keys(storageData.sync));
// 3. 检查页面元素,寻找收藏数据
console.log('\n3. 检查页面元素...');
// 查找所有可能包含收藏的元素
const possibleSelectors = [
'.site-item', '.bookmark-item', '.fav-item', '.website-item',
'.card', '.item', '.tile', '.box',
'[data-site]', '[data-url]', '[data-bookmark]'
];
let allItems = [];
possibleSelectors.forEach(selector => {
const elements = document.querySelectorAll(selector);
if (elements.length > 0) {
console.log(`发现 ${elements.length} 个 ${selector} 元素`);
elements.forEach(el => {
try {
// 尝试获取标题和URL
let title = el.textContent.trim() || el.getAttribute('title') || '无标题';
let url = '';
// 检查是否有直接链接
if (el.href) {
url = el.href;
}
// 检查 data 属性
else if (el.dataset.url) {
url = el.dataset.url;
}
else if (el.getAttribute('data-url')) {
url = el.getAttribute('data-url');
}
// 检查子元素中的链接
else {
const linkEl = el.querySelector('a[href]');
if (linkEl) {
url = linkEl.href;
title = linkEl.textContent.trim() || title;
}
}
if (url && url.startsWith('http')) {
allItems.push({ title, url, selector });
}
} catch (e) {
console.error('解析元素失败:', e);
}
});
}
});
// 去重
const uniqueItems = [...new Map(allItems.map(item => [item.url, item])).values()];
console.log(`\n找到 ${uniqueItems.length} 个唯一的外部链接`);
// 4. 检查扩展的 indexedDB 数据库
console.log('\n4. 检查扩展的 IndexedDB 数据库...');
// 扩展的 indexedDB 数据库名通常包含扩展 ID
const extensionId = window.location.hostname;
console.log('扩展 ID:', extensionId);
if (window.indexedDB) {
indexedDB.databases().then(databases => {
console.log('发现 IndexedDB 数据库:', databases);
// 尝试读取与扩展相关的数据库
const extensionDatabases = databases.filter(db =>
db.name && (db.name.includes(extensionId) || db.name.includes('monknow'))
);
console.log('与扩展相关的数据库:', extensionDatabases);
// 5. 下载所有数据
console.log('\n5. 准备下载所有数据...');
const exportData = {
timestamp: new Date().toISOString(),
extensionId: extensionId,
pageUrl: window.location.href,
storageData: storageData,
pageItems: uniqueItems,
indexedDBDatabases: databases
};
// 下载数据
const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'monknow-extension-data.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
console.log('\n=== 导出完成 ===');
console.log('已下载扩展数据文件: monknow-extension-data.json');
console.log('\n数据文件包含:');
console.log('- Chrome 扩展存储数据 (local 和 sync)');
console.log('- 页面上的所有外部链接');
console.log('- 扩展相关的 IndexedDB 数据库信息');
// 尝试提取收藏数据
console.log('\n6. 尝试提取收藏数据...');
// 检查存储数据中是否有收藏相关的键
const possibleKeys = ['sites', 'bookmarks', 'favorites', 'websites', 'urls', 'data'];
let foundBookmarks = [];
// 检查存储数据
Object.values(storageData).forEach(storage => {
Object.entries(storage).forEach(([key, value]) => {
possibleKeys.forEach(possibleKey => {
if (key.toLowerCase().includes(possibleKey) ||
(typeof value === 'object' && value !== null &&
(Array.isArray(value) || Object.values(value).some(v =>
typeof v === 'object' && v !== null && (v.url || v.link))))
) {
console.log(`\n发现可能包含收藏的数据: ${key}`);
console.log('数据类型:', typeof value);
// 尝试解析为收藏
try {
if (Array.isArray(value)) {
const bookmarks = value.filter(item =>
item && typeof item === 'object' && (item.url || item.link)
).map(item => ({
title: item.title || item.name || '无标题',
url: item.url || item.link,
from: `storage.${key}`
}));
foundBookmarks.push(...bookmarks);
} else if (typeof value === 'object') {
// 处理对象类型
Object.values(value).forEach(item => {
if (item && typeof item === 'object' && (item.url || item.link)) {
foundBookmarks.push({
title: item.title || item.name || '无标题',
url: item.url || item.link,
from: `storage.${key}`
});
}
});
}
} catch (e) {
console.error('解析收藏数据失败:', e);
}
}
});
});
});
// 合并页面数据和存储数据
const allBookmarks = [...foundBookmarks, ...uniqueItems];
const finalBookmarks = [...new Map(allBookmarks.map(b => [b.url, b])).values()];
console.log(`\n共提取到 ${finalBookmarks.length} 个收藏项`);
// 如果有收藏项,下载单独的收藏文件
if (finalBookmarks.length > 0) {
console.log('\n7. 下载收藏数据...');
const bookmarksData = {
timestamp: new Date().toISOString(),
total: finalBookmarks.length,
bookmarks: finalBookmarks
};
const bookmarksBlob = new Blob([JSON.stringify(bookmarksData, null, 2)], { type: 'application/json' });
const bookmarksUrl = URL.createObjectURL(bookmarksBlob);
const bookmarksA = document.createElement('a');
bookmarksA.href = bookmarksUrl;
bookmarksA.download = 'monknow-bookmarks.json';
document.body.appendChild(bookmarksA);
bookmarksA.click();
document.body.removeChild(bookmarksA);
URL.revokeObjectURL(bookmarksUrl);
console.log('已下载收藏文件: monknow-bookmarks.json');
console.log('收藏项列表:');
finalBookmarks.forEach((bookmark, index) => {
console.log(`${index + 1}. ${bookmark.title} - ${bookmark.url}`);
});
}
console.log('\n=== 导出总结 ===');
console.log(`总收藏项: ${finalBookmarks.length}`);
console.log('来自存储数据:', foundBookmarks.length);
console.log('来自页面元素:', uniqueItems.length);
console.log('\n请查看下载的文件,获取完整的导出数据。');
}).catch(error => {
console.error('检查 IndexedDB 失败:', error);
});
} else {
console.error('浏览器不支持 IndexedDB');
}
});
} else {
console.error('Chrome 扩展存储 API 不可用');
console.error('请确保在 MonKonw 扩展页面中执行此脚本,并且扩展具有 storage 权限。');
}
})();
脚本工作原理
这个脚本专门针对Chrome扩展设计,使用了Chrome扩展特有的 chrome.storage API,这是Chrome扩展存储数据的主要方式(Edge浏览器也可)。脚本会:
- 检查是否在MonKonw扩展页面中执行
- 使用 chrome.storage.local 和 chrome.storage.sync 读取扩展存储的所有数据
- 检查页面上的所有元素,寻找收藏的网页链接
- 检查扩展的IndexedDB数据库
- 下载包含所有数据的JSON文件
- 尝试从存储数据中提取收藏项,并单独下载一个收藏文件
- 显示详细的导出总结