WechatExporter icon indicating copy to clipboard operation
WechatExporter copied to clipboard

[feature] 数据和 前端 html 分离

Open lqzhgood opened this issue 5 years ago • 21 comments

现在通过 数据+模板 的形式生成的静态 html 巨大无比,打开就卡死。。。

能否参照 http://wxbackup.imxfd.com/ 的实现。(Demo http://wxbackup.imxfd.com/demo/index.html) 导出 JSON 数据和资源

完全前端分离,前端通过读取 JSON 数据的形式客户端渲染。

  • 懒加载、分页加载等形式更好实现。
  • 可以间接提供 JSON 原始数据的导出 更方便别人使用
  • 消息类型 type=10000 里面还可以细分 挪到前端处理更方便 不用每次编译导出端

如果可以的话,我可以提供完全的前端 PR 支持。

// 资源(图片、视频等)建议还是使用源文件名,文件名可能带有部分 “可用” 信息

lqzhgood avatar Feb 01 '21 07:02 lqzhgood

现在通过 数据+模板 的形式生成的静态 html 巨大无比,打开就卡死。。。

能否参照 http://wxbackup.imxfd.com/ 的实现。(Demo http://wxbackup.imxfd.com/demo/index.html) 导出 JSON 数据和资源

完全前端分离,前端通过读取 JSON 数据的形式客户端渲染。

  • 懒加载、分页加载等形式更好实现。
  • 可以间接提供 JSON 原始数据的导出 更方便别人使用
  • 消息类型 type=10000 里面还可以细分 挪到前端处理更方便 不用每次编译导出端

如果可以的话,我可以提供完全的前端 PR 支持。

// 资源(图片、视频等)建议还是使用源文件名,文件名可能带有部分 “可用” 信息

好啊,改成输出json技术上没啥问题,我想想看输出格式(或者你有什么建议)。如果你能支持前端那太好了!

BlueMatthew avatar Feb 01 '21 09:02 BlueMatthew

主要是微信的不同消息的字段不太一样,当然可以通过json对象的字段存在不存在来解决,另外,怎么分页也是一个问题(或者滑动时加载?)。

BlueMatthew avatar Feb 01 '21 09:02 BlueMatthew

我刚好在做一个消息展示的 “系统”,把QQ、微信、短信、通话、邮件都整合在一起查看。 前端已经写完了,后端数据获取只剩微信了。 目前微信用的 wxbackup.imxfd.com 不过我想开源做,前者不是开源的,所以直接把你这里整合一下就完工了。

我现在不知道微信数据库里面数据结构啥样的,我觉得原样完整输出比较好,然后还有资源的完整导出。

这有个读数据库的方法 我还没试 https://github.com/contr4l/MicromsgHistory

你也可以看看 http://wxbackup.imxfd.com/demo/js/message.js 这个的输出结构 (感觉这个就是把数据库的数据完整输出了 没做处理)。

可以的话,一起搞个大事情呗~

lqzhgood avatar Feb 01 '21 11:02 lqzhgood

我刚好在做一个消息展示的 “系统”,把QQ、微信、短信、通话、邮件都整合在一起查看。 前端已经写完了,后端数据获取只剩微信了。 目前微信用的 wxbackup.imxfd.com 不过我想开源做,前者不是开源的,所以直接把你这里整合一下就完工了。

我现在不知道微信数据库里面数据结构啥样的,我觉得原样完整输出比较好,然后还有资源的完整导出。

这有个读数据库的方法 我还没试 https://github.com/contr4l/MicromsgHistory

你也可以看看 http://wxbackup.imxfd.com/demo/js/message.js 这个的输出结构 (感觉这个就是把数据库的数据完整输出了 没做处理)。

可以的话,一起搞个大事情呗~ 加个 Q 聊聊? http://n.lqzh.me/qq

你这个消息展示的系统也是一个app吗?如果是一个app,那实时获得消息应该做不到呢。如果只是备份性质的,时效性可能差一些吧。

wxbackup.imxfd.com 我应该用过,好像没有导成功,所以后来才找到了WechatExporter-iOS,以及现在自己又重新实现了。回头我再试试 wxbackup.imxfd.com。

微信有各种消息类型的结构,估计也是历史的原因,结构也大多不统一的,或者说蛮乱的。完全结构化数据需要好好整理一下。

BlueMatthew avatar Feb 01 '21 15:02 BlueMatthew

主要结构就分 text xml。 我的意见是在导出为 JSON 的过程中不要去解析 XML。
由前端来解析 XML 并分类格式,这样的好处是即便是未知的 XML, 前端也能显示信息(只是没适配样式)

附现在整理的 typeMap

async function typeMap(v, ov) {

    if (v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 1) {
        // return {type: '含链接文本'};
        return {
            type: '文本', 
        };
    }

    if (v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 2) {
        return {
            type: '微信运动', 
        };
    }


    const f_share1 = v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 3;
    const f_share2 = v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 5;
    if (f_share1 || f_share2) {
        return {
            type: '分享', 
        };
    }

    if (v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 6) {
        // TODO 导出文件 建立链接
        return {
            type: '文件', 
        };
    }

    if (v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 17) {
        return {
            type: '位置共享', 
        };
    }

    if (v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 19) {

        return {
            type: '聊天记录', 
        };
    }

    const f_app1 = v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 33;
    const f_app2 = v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 36;
    if (f_app1 || f_app2) {
        await downFile(v, 'app', ['m_nsContent.msg.appmsg.weappinfo.weappiconurl'], 'url_icon');
        return {
            type: '小程序', 
        };
    }

    if (v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 2000) {
        return {
            type: '转账', 
        };
    }


    if (v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 2001) {
        return {
            type: '红包', 
        };
    }


    const f_emoji1 = v.m_uiMessageType == 49 && _.get(v, 'm_nsContent.msg.appmsg.type') == 8;
    if (v.m_uiMessageType == 47 || f_emoji1) {
        // TODO 补全
        // await downFile(v, 'emoji', ['m_nsContent.msg.emoji.cdnurl', 'm_nsContent.msg.emoji.thumburl'], 'url_emoji');
        return {
            type: '自定义表情', 
        };
    }


    switch (v.m_uiMessageType) {
        case 1:
            // item.m_uiMessageType == 1
            return {
                type: '文本', 
            };
        case 3:
            // item.m_uiMessageType == 3 
            // TODO 导出文件 建立链接
            return {
                type: '图片', 
            };
        case 34:
            // item.m_uiMessageType == 34
            // TODO 导出文件 建立链接
            return {
                type: '语音', 
            };
        case 38:
            // item.m_uiMessageType == 38
            return {
                type: '撤回消息', 
            };
        case 42:
            // item.m_uiMessageType == 42
            await downFile(v, 'userCard', ['m_nsContent.msg.bigheadimgurl', 'm_nsContent.msg.brandIconUrl'], 'url_cover');
            return {
                type: '名片', 
            };
        case 43:
        case 62:
            // item.m_uiMessageType == 62 || item.m_uiMessageType == 43) 
            return {
                type: '视频', 
            };
        case 48:
            // item.m_uiMessageType == 48
            return {
                type: '位置', 
            };
        case 49:
            // 未知的其他链接 理论上这里应该在上面全都被 if 'm_nsContent.msg.appmsg.type' 处理掉
            return {
                type: '链接', 
            };
        case 50:
            // item.m_uiMessageType == 50
            return {
                type: '视频聊天', 
            };
        case 10000:
            // item.m_uiMessageType == 10000
           // TODO 需要细分
            return {
                type: '系统消息', 
            };
        default:
            throw new Error(`unknown Type ${v}`);
    }
}

lqzhgood avatar Feb 02 '21 02:02 lqzhgood

image

我觉得按 3 部分来做比较妥当。

  1. 数据库导出 --> 此处仅导出原始表数据为,按 Key-Value导出 JSON ,不做额外处理。
  2. 数据转换 --> 处理为标准数据结构
  3. 前端使用 2 的数据做展示。

2 3 我基本完成了。 1 中的 ~SEMI_XML~ 我不晓得怎么处理。。

lqzhgood avatar Feb 04 '21 06:02 lqzhgood

原先的想法是导出一个最简单的格式,在10年,20年之后的系统中还都能浏览这些信息,所以没有整太多的东西,当然h5也不是我擅长的 :),不过一个页面太多内容,确实第一次加载是一个问题,我先试试用简单的分页方式能不能解决。

晚点我在看一下怎么和你的这些个结构对应起来来输出一个json数据。

BlueMatthew avatar Feb 04 '21 08:02 BlueMatthew

上图是我从 安卓 微信数据库 里面的截图,不知道和 IOS 上是否一样。 JSON 按照表直接输出就行了。

{
    msgId:  xxx,
    msgSvrId: xxx
    type: xxxxx
   .....
}

只是 content 里面包含 ~SEMI_XML~ 格式的数据我不知道怎么解析 不知道 IOS 的数据库里面是否包含此结构~

lqzhgood avatar Feb 04 '21 08:02 lqzhgood

上图是我从 安卓 微信数据库 里面的截图,不知道和 IOS 上是否一样。 JSON 按照表直接输出就行了。

{
    msgId:  xxx,
    msgSvrId: xxx
    type: xxxxx
   .....
}

只是 content 里面包含 ~SEMI_XML~ 格式的数据我不知道怎么解析 不知道 IOS 的数据库里面是否包含此结构~

差不多的,貌似ios更少一些字段。xml其实都是自己猜的,需要不停的维护

BlueMatthew avatar Feb 04 '21 09:02 BlueMatthew

IOS 上都是纯 XML 文本么?

我说的 ~SEMI_XML~ 是需要通过二进制解析的。 直接文本是乱码

https://www.52pojie.cn/thread-1039879-1-1.html

lqzhgood avatar Feb 04 '21 09:02 lqzhgood

IOS 上都是纯 XML 文本么?

我说的 ~SEMI_XML~ 是需要通过二进制解析的。 直接文本是乱码

https://www.52pojie.cn/thread-1039879-1-1.html

ios并没有做这样的编码,基本上都是明文xml,反倒是控制数据,基本都是二进制的。

BlueMatthew avatar Feb 04 '21 09:02 BlueMatthew

刚才测试了一下分页加载,但是看起来,动态加载外部数据是一个问题,我原先的想法是,一般人都不会有web server,最简单的方法就是双击这个html页面,浏览器就能打开(file://协议)然后查看聊天记录。内嵌的内容都可以正常加载,但是再加载外部数据会被安全机制阻止,关于这个,你有什么好的建议吗?

BlueMatthew avatar Feb 04 '21 11:02 BlueMatthew

内容一次读入内存。 分页在前端处理。

内容可以写入一个 js 内容是

var msgArr = [
      ....
]

分页数据通过 msgArr.slice( sPage , sPage + PageNum) 拿每页的数据进行渲染。


by the way
(file://协议) 限制太多了,我想找一个简单的 web server。 双击这个 webServer.exe 自动起本目录的静态内容,并打开浏览器显示。

lqzhgood avatar Feb 04 '21 13:02 lqzhgood

内容一次读入内存。 分页在前端处理。

内容可以写入一个 js 内容是

var msgArr = [
      ....
]

分页数据通过 msgArr.slice( sPage , sPage + PageNum) 拿每页的数据进行渲染。

by the way (file://协议) 限制太多了,我想找一个简单的 web server。 双击这个 webServer.exe 自动起本目录的静态内容,并打开浏览器显示。

嗯,我也是这么想,数据加载的成本看来减少不了,只能减少第一次dom加载的成本了。今天试试。

web server还是有点重,我这个小工具就不考虑了 :)

BlueMatthew avatar Feb 04 '21 23:02 BlueMatthew

miniserve – 只有 776KB 的临时文件分享服务器

https://www.appinn.com/miniserve-github/

lqzhgood avatar Feb 05 '21 01:02 lqzhgood

我想要做一个APP只用来展示微信和QQ的历史记录查看功能,找了很多读取微信数据库的方法《https://github.com/allen1881996/WeChat-Data-Analysis》 《http://wxbackup.imxfd.com/demo/js/message.js》这两个都试了,就感觉这个作者的这个效果最好,数据最全,可惜不会c++[流泪]。迫切想要一个数据能够分离出来,然后自己导入到数据库中,用自己做的APP来加载历史数据。给作者比个心[heart]

chenzao1024 avatar Aug 23 '21 15:08 chenzao1024

这个想法好棒,有更新嘛? 我觉得结构化数据是基础,只要有了相对统一的数据接口,前端能做的很多 数据要不要独立存放我觉得是另一回事,完全可以提供一个方法单独导出数据,但是把数据合并到 html 里就像 owner 说的对普通用户更友好一点 而且我估计卡顿更多是渲染过多 dom 导致的,io 影响有限,如果一次读取到内存里前端分页其实跟合并数据到 html 里没有什么特别大的区别。dom 里长列表的优化方法还是有不少的

haven2world avatar Mar 27 '22 07:03 haven2world

这个想法好棒,有更新嘛? 我觉得结构化数据是基础,只要有了相对统一的数据接口,前端能做的很多 数据要不要独立存放我觉得是另一回事,完全可以提供一个方法单独导出数据,但是把数据合并到 html 里就像 owner 说的对普通用户更友好一点 而且我估计卡顿更多是渲染过多 dom 导致的,io 影响有限,如果一次读取到内存里前端分页其实跟合并数据到 html 里没有什么特别大的区别。dom 里长列表的优化方法还是有不少的

因为最初纯粹了是为了备份和娃有关的群的聊天消息,并没有去考虑那么多后期展示的问题,只是想10年,20年后能正常打开就可以了。所以一开始都没有考虑异步加载,后来改成异步加载了,html数据被扔到一个json中(异步加载也应该能继续优化),只是并没有做成纯数据方式。后面可以考虑优化。

BlueMatthew avatar Mar 27 '22 12:03 BlueMatthew

前后端我都快写完了,但是还有很多细节还在整,最近比较忙,大概3个月后放出。


不单纯是数据和页面分离,还有“大数据”的一些图表和词云等
也不限于微信,想做成通用的,这样 QQ 、邮件、通话记录等能一并显示。
希望到时候楼主能提供 微信的 IOS 端的数据支持 (安卓端/Windows 我已完成)
所以工作量略大……

lqzhgood avatar Mar 28 '22 09:03 lqzhgood

非常期待导出为JSON格式

zengbo avatar Nov 17 '22 11:11 zengbo

跳票也快一年~ 真的是太难了~ 终于写完了, 现在补充文档中...

可以看下 Demo https://github.com/lqzhgood/Shmily-Show-Demo 文档还在每日补充中, 核心部分写完了 https://github.com/lqzhgood/Shmily

LZ 如果有兴趣可以共建~ LZ 完成 IOS 数据库导出这一步就行了 ( 参考文档 理念 Get-ExportDB ) 后面 数据导出 和 资源导出 应该和 Android 一样, 我已经完成了

lqzhgood avatar Feb 10 '23 01:02 lqzhgood