update readme

This commit is contained in:
shuaikangzhou 2023-11-16 23:56:36 +08:00
parent 9c7cb674f8
commit 8a4c9a04b7
12 changed files with 189 additions and 53 deletions

View File

@ -4,11 +4,18 @@
<option name="autoReloadType" value="SELECTIVE" /> <option name="autoReloadType" value="SELECTIVE" />
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="84e65474-7da9-466d-baf3-cc88dde3ffdd" name="变更" comment="新增聊天记录导出csv格式"> <list default="true" id="84e65474-7da9-466d-baf3-cc88dde3ffdd" name="变更" comment="导出所有数据库的聊天记录">
<change afterPath="$PROJECT_DIR$/doc/images/pc_contact.png" afterDir="false" />
<change afterPath="$PROJECT_DIR$/doc/电脑端使用教程.md" afterDir="false" />
<change afterPath="$PROJECT_DIR$/main_pc.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/DataBase/micro_msg.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/micro_msg.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/person.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/person.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/DataBase/msg.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/DataBase/msg.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/mainview.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/mainview.py" afterDir="false" /> <change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.ui" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/decryptUi.ui" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/pc_decrypt.py" beforeDir="false" afterPath="$PROJECT_DIR$/app/ui_pc/tool/pc_decrypt/pc_decrypt.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/decrypt_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/decrypt_window.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/doc/数据库介绍.md" beforeDir="false" afterPath="$PROJECT_DIR$/doc/数据库介绍.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/readme.md" beforeDir="false" afterPath="$PROJECT_DIR$/readme.md" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -80,7 +87,7 @@
<option name="stateVersion" value="1" /> <option name="stateVersion" value="1" />
</component> </component>
<component name="ProblemsViewState"> <component name="ProblemsViewState">
<option name="selectedTabId" value="ProjectErrors" /> <option name="selectedTabId" value="CurrentFile" />
</component> </component>
<component name="ProjectId" id="2JrtgPdd86dlNq47HAnVDPZuCVh" /> <component name="ProjectId" id="2JrtgPdd86dlNq47HAnVDPZuCVh" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" /> <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
@ -88,15 +95,15 @@
<option name="hideEmptyMiddlePackages" value="true" /> <option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" /> <option name="showLibraryContents" value="true" />
</component> </component>
<component name="PropertiesComponent">{ <component name="PropertiesComponent"><![CDATA[{
&quot;keyToString&quot;: { "keyToString": {
&quot;DefaultHtmlFileTemplate&quot;: &quot;HTML File&quot;, "DefaultHtmlFileTemplate": "HTML File",
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;, "RunOnceActivity.OpenProjectViewOnStart": "true",
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, "RunOnceActivity.ShowReadmeOnStart": "true",
&quot;last_opened_file_path&quot;: &quot;D:/Program Files/Python310/Scripts/pyuic5.exe&quot;, "last_opened_file_path": "D:/Program Files/Python310/Scripts/pyuic5.exe",
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot; "settings.editor.selected.configurable": "editor.preferences.tabs"
} }
}</component> }]]></component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS"> <key name="MoveFile.RECENT_KEYS">
<recent name="D:\Project\Python\WeChatMsg\app\ui_pc\tool" /> <recent name="D:\Project\Python\WeChatMsg\app\ui_pc\tool" />
@ -104,7 +111,7 @@
<recent name="D:\Project\PythonProject\WeChatMsg\app\Ui" /> <recent name="D:\Project\PythonProject\WeChatMsg\app\Ui" />
</key> </key>
</component> </component>
<component name="RunManager" selected="Python.decrypt_window"> <component name="RunManager" selected="Python.main_pc">
<configuration name="decrypt_window" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true"> <configuration name="decrypt_window" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="WeChatMsg" /> <module name="WeChatMsg" />
<option name="INTERPRETER_OPTIONS" value="" /> <option name="INTERPRETER_OPTIONS" value="" />
@ -147,7 +154,7 @@
<option name="INPUT_FILE" value="" /> <option name="INPUT_FILE" value="" />
<method v="2" /> <method v="2" />
</configuration> </configuration>
<configuration name="misc" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true"> <configuration name="main_pc" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="WeChatMsg" /> <module name="WeChatMsg" />
<option name="INTERPRETER_OPTIONS" value="" /> <option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" /> <option name="PARENT_ENVS" value="true" />
@ -155,11 +162,11 @@
<env name="PYTHONUNBUFFERED" value="1" /> <env name="PYTHONUNBUFFERED" value="1" />
</envs> </envs>
<option name="SDK_HOME" value="" /> <option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/app/DataBase" /> <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" /> <option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" /> <option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/app/DataBase/misc.py" /> <option name="SCRIPT_NAME" value="$PROJECT_DIR$/main_pc.py" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" /> <option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" /> <option name="EMULATE_TERMINAL" value="false" />
@ -233,11 +240,11 @@
</configuration> </configuration>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Python.main_pc" />
<item itemvalue="Python.decrypt_window" /> <item itemvalue="Python.decrypt_window" />
<item itemvalue="Python.msg" /> <item itemvalue="Python.msg" />
<item itemvalue="Python.test" /> <item itemvalue="Python.test" />
<item itemvalue="Python.main" /> <item itemvalue="Python.main" />
<item itemvalue="Python.misc" />
</list> </list>
</recent_temporary> </recent_temporary>
</component> </component>
@ -253,13 +260,6 @@
<option name="presentableId" value="Default" /> <option name="presentableId" value="Default" />
<updated>1672848140146</updated> <updated>1672848140146</updated>
</task> </task>
<task id="LOCAL-00017" summary="修复了Webengine横向小的问题">
<created>1680670947385</created>
<option name="number" value="00017" />
<option name="presentableId" value="LOCAL-00017" />
<option name="project" value="LOCAL" />
<updated>1680670947385</updated>
</task>
<task id="LOCAL-00018" summary="新增聊天报告"> <task id="LOCAL-00018" summary="新增聊天报告">
<created>1682305451381</created> <created>1682305451381</created>
<option name="number" value="00018" /> <option name="number" value="00018" />
@ -596,7 +596,14 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1700145601841</updated> <updated>1700145601841</updated>
</task> </task>
<option name="localTasksCounter" value="66" /> <task id="LOCAL-00066" summary="导出所有数据库的聊天记录">
<created>1700147800698</created>
<option name="number" value="00066" />
<option name="presentableId" value="LOCAL-00066" />
<option name="project" value="LOCAL" />
<updated>1700147800698</updated>
</task>
<option name="localTasksCounter" value="67" />
<servers /> <servers />
</component> </component>
<component name="UnknownFeatures"> <component name="UnknownFeatures">
@ -632,7 +639,6 @@
</option> </option>
</component> </component>
<component name="VcsManagerConfiguration"> <component name="VcsManagerConfiguration">
<MESSAGE value="修复部分bug" />
<MESSAGE value="替换chat里的contact" /> <MESSAGE value="替换chat里的contact" />
<MESSAGE value="增加中文路径提示" /> <MESSAGE value="增加中文路径提示" />
<MESSAGE value="用stackWidget重写contactUI" /> <MESSAGE value="用stackWidget重写contactUI" />
@ -657,7 +663,8 @@
<MESSAGE value="修复db文件空格路径的bug" /> <MESSAGE value="修复db文件空格路径的bug" />
<MESSAGE value="修复情感分析数值显示过长的bug" /> <MESSAGE value="修复情感分析数值显示过长的bug" />
<MESSAGE value="新增聊天记录导出csv格式" /> <MESSAGE value="新增聊天记录导出csv格式" />
<option name="LAST_COMMIT_MESSAGE" value="新增聊天记录导出csv格式" /> <MESSAGE value="导出所有数据库的聊天记录" />
<option name="LAST_COMMIT_MESSAGE" value="导出所有数据库的聊天记录" />
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" /> <option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" />
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" /> <option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" />
</component> </component>

View File

@ -46,6 +46,8 @@ class ContactPC:
# Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl # Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
self.alias = contact_info.get('Alias') self.alias = contact_info.get('Alias')
self.nickName = contact_info.get('NickName') self.nickName = contact_info.get('NickName')
if not self.remark:
self.remark = self.nickName
self.smallHeadImgUrl = contact_info.get('smallHeadImgUrl') self.smallHeadImgUrl = contact_info.get('smallHeadImgUrl')
self.smallHeadImgBLOG = b'' self.smallHeadImgBLOG = b''
self.avatar = QPixmap() self.avatar = QPixmap()

View File

@ -51,7 +51,9 @@ class Ui_Dialog(object):
self.label_7.setObjectName("label_7") self.label_7.setObjectName("label_7")
self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1) self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1)
self.lineEdit = QtWidgets.QLineEdit(Dialog) self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setStyleSheet("background:transparent;border-width:0;border-style:outset") self.lineEdit.setStyleSheet("\n"
" background:transparent;border-width:0;border-style:outset\n"
" ")
self.lineEdit.setFrame(False) self.lineEdit.setFrame(False)
self.lineEdit.setObjectName("lineEdit") self.lineEdit.setObjectName("lineEdit")
self.gridLayout.addWidget(self.lineEdit, 4, 1, 1, 1) self.gridLayout.addWidget(self.lineEdit, 4, 1, 1, 1)
@ -62,6 +64,7 @@ class Ui_Dialog(object):
self.label_6.setObjectName("label_6") self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1) self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.label_key = QtWidgets.QLabel(Dialog) self.label_key = QtWidgets.QLabel(Dialog)
self.label_key.setMaximumSize(QtCore.QSize(200, 16777215))
self.label_key.setText("") self.label_key.setText("")
self.label_key.setObjectName("label_key") self.label_key.setObjectName("label_key")
self.gridLayout.addWidget(self.label_key, 5, 1, 1, 1) self.gridLayout.addWidget(self.label_key, 5, 1, 1, 1)
@ -90,6 +93,7 @@ class Ui_Dialog(object):
self.label_8.setObjectName("label_8") self.label_8.setObjectName("label_8")
self.gridLayout.addWidget(self.label_8, 6, 0, 1, 1) self.gridLayout.addWidget(self.label_8, 6, 0, 1, 1)
self.label_db_dir = QtWidgets.QLabel(Dialog) self.label_db_dir = QtWidgets.QLabel(Dialog)
self.label_db_dir.setMaximumSize(QtCore.QSize(200, 300))
self.label_db_dir.setText("") self.label_db_dir.setText("")
self.label_db_dir.setObjectName("label_db_dir") self.label_db_dir.setObjectName("label_db_dir")
self.gridLayout.addWidget(self.label_db_dir, 6, 1, 1, 1) self.gridLayout.addWidget(self.label_db_dir, 6, 1, 1, 1)

View File

@ -117,6 +117,12 @@
</item> </item>
<item row="5" column="1"> <item row="5" column="1">
<widget class="QLabel" name="label_key"> <widget class="QLabel" name="label_key">
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -173,6 +179,12 @@
</item> </item>
<item row="6" column="1"> <item row="6" column="1">
<widget class="QLabel" name="label_db_dir"> <widget class="QLabel" name="label_db_dir">
<property name="maximumSize">
<size>
<width>200</width>
<height>300</height>
</size>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>

View File

@ -46,6 +46,7 @@ class DecryptControl(QWidget, decryptUi.Ui_Dialog):
self.label_pid.setText(str(self.info['pid'])) self.label_pid.setText(str(self.info['pid']))
self.label_version.setText(self.info['version']) self.label_version.setText(self.info['version'])
self.lineEdit.setFocus() self.lineEdit.setFocus()
self.checkBox.setChecked(True)
if self.wx_dir and os.path.exists(os.path.join(self.wx_dir, self.info['wxid'])): if self.wx_dir and os.path.exists(os.path.join(self.wx_dir, self.info['wxid'])):
self.label_ready.setText('已就绪') self.label_ready.setText('已就绪')
except Exception as e: except Exception as e:
@ -59,6 +60,7 @@ class DecryptControl(QWidget, decryptUi.Ui_Dialog):
if directory: if directory:
self.label_db_dir.setText(directory) self.label_db_dir.setText(directory)
self.wx_dir = directory self.wx_dir = directory
self.checkBox_2.setChecked(True)
if self.ready: if self.ready:
self.label_ready.setText('已就绪') self.label_ready.setText('已就绪')

View File

@ -1,11 +1,9 @@
import ctypes import ctypes
import sys import sys
import time
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import * from PyQt5.QtWidgets import *
from app.ui_pc import mainview
from app.ui_pc.tool.pc_decrypt import pc_decrypt from app.ui_pc.tool.pc_decrypt import pc_decrypt
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport") ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
@ -28,23 +26,6 @@ class ViewController(QWidget):
self.viewDecrypt.DecryptSignal.connect(self.show_success) self.viewDecrypt.DecryptSignal.connect(self.show_success)
self.viewDecrypt.show() self.viewDecrypt.show()
def loadMainWinView(self, username=None):
"""
聊天界面
:param username: 账号
:return:
"""
username = ''
start = time.time()
self.viewMainWIn = mainview.MainWinController(username=username)
self.viewMainWIn.setWindowTitle("Chat")
# print(username)
self.viewMainWIn.username = username
# self.viewMainWIn.exitSignal.connect(self.loadDecryptView) # 不需要回到登录界面可以省略
self.viewMainWIn.show()
end = time.time()
print('ok', end - start)
def show_success(self): def show_success(self):
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下") QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
@ -52,7 +33,5 @@ class ViewController(QWidget):
if __name__ == '__main__': if __name__ == '__main__':
app = QApplication(sys.argv) app = QApplication(sys.argv)
view = ViewController() view = ViewController()
# view.loadPCDecryptView() view.loadPCDecryptView()
view.loadMainWinView()
# view.show_success()
sys.exit(app.exec_()) sys.exit(app.exec_())

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

BIN
doc/images/pc_contact.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -1,3 +1,4 @@
# 微信数据库介绍 # 微信数据库介绍
**这个人比较懒,还什么都没写** **这个人比较懒,还什么都没写**

View File

@ -0,0 +1,70 @@
# 一、解密微信数据库
## 主要功能
1. 解密微信数据库
2. 查看聊天记录
3. 导出聊天记录
* CSV
* docx(待实现)
* HTML(待实现)
## 安装
```shell
git clone https://github.com/LC044/WeChatMsg
cd WeChatMsg
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
```
## 解密
<details>
解密步骤:
1. 登录微信
2. 运行程序
```shell
python decrypt_window.py
```
3. 点击获取信息
![](./images/pc_decrypt_info.png)
4. 设置微信安装路径
可以到微信->设置->文件管理查看
![](./images/setting.png)
点击**设置微信路径**按钮,选择该文件夹路径
5. 获取到密钥和微信路径之后点击开始解密
6. 解密后的数据库文件保存在./app/DataBase/Msg路径下
</details>
## 查看聊天记录
<details>
1. 运行程序
```shell
python main_pc.py
```
2. 选择联系人
<img src='./images/pc_contact.png' alt="运行图片"/>
3. 导出聊天记录
聊天记录保存在 **/data/聊天记录/** 文件夹下
<img src='./images/messages_demo.png' />
</details>

58
main_pc.py Normal file
View File

@ -0,0 +1,58 @@
import ctypes
import sys
import time
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import *
from app.ui_pc import mainview
from app.ui_pc.tool.pc_decrypt import pc_decrypt
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("WeChatReport")
class ViewController(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle('解密')
self.setWindowIcon(QIcon('./app/data/icons/logo.svg'))
self.viewMainWIn = None
self.viewDecrypt = None
def loadPCDecryptView(self):
"""
登录界面
:return:
"""
self.viewDecrypt = pc_decrypt.DecryptControl()
self.viewDecrypt.DecryptSignal.connect(self.show_success)
self.viewDecrypt.show()
def loadMainWinView(self, username=None):
"""
聊天界面
:param username: 账号
:return:
"""
username = ''
start = time.time()
self.viewMainWIn = mainview.MainWinController(username=username)
self.viewMainWIn.setWindowTitle("Chat")
# print(username)
self.viewMainWIn.username = username
# self.viewMainWIn.exitSignal.connect(self.loadDecryptView) # 不需要回到登录界面可以省略
self.viewMainWIn.show()
end = time.time()
print('ok', end - start)
def show_success(self):
QMessageBox.about(self, "解密成功", "数据库文件存储在\napp/DataBase/Msg\n文件夹下")
if __name__ == '__main__':
app = QApplication(sys.argv)
view = ViewController()
# view.loadPCDecryptView()
view.loadMainWinView()
# view.show_success()
sys.exit(app.exec_())

View File

@ -94,7 +94,8 @@ pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
随便下载一个SQLite数据库查看软件就能打开数据库例如[DB Browser for SQLite](https://sqlitebrowser.org/dl/) 随便下载一个SQLite数据库查看软件就能打开数据库例如[DB Browser for SQLite](https://sqlitebrowser.org/dl/)
[数据库功能介绍](./doc/数据库介绍.md) * [数据库功能介绍](./doc/数据库介绍.md)
* [更多功能介绍](./doc/电脑端使用教程.md)
</details> </details>