支持导出音乐类型的记录
This commit is contained in:
parent
225123d291
commit
3e00811e1c
@ -34,13 +34,17 @@
|
||||
|
||||
## 2. 已知问题
|
||||
|
||||
* 视频下载不稳定(如有解决方案欢迎PR)
|
||||
* 视频下载不稳定,视频可能不全(如有解决方案欢迎PR)
|
||||
* 只能开小号导出自己朋友圈(如有解决方案欢迎PR)
|
||||
* HTML页面比较原始
|
||||
* 音乐等朋友圈格式不支持
|
||||
* 自动浏览朋友圈的功能不稳定(如有解决方案欢迎PR)
|
||||
|
||||
|
||||
## 3. 常见问题与解决方法
|
||||
问:怎么导出自己朋友圈
|
||||
- 近期的朋友圈可以浏览全部朋友,然后导出好友列表选自己
|
||||
- 需要导出长期的话,请开个小号然后使用搜一搜,详见[电脑微信浏览朋友圈](/doc/manual_guide.md)
|
||||
|
||||
问:为什么导出的数据不全?
|
||||
- 答:软件只能导出在电脑微信**浏览过**的朋友圈记录,未浏览过的无法导出。
|
||||
|
||||
|
@ -39,6 +39,8 @@ class Media:
|
||||
thumb: Optional[Thumb] = None
|
||||
thumbUrl: Optional[str] = None
|
||||
videoDuration: Optional[str] = None
|
||||
title: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
@dataclass_json
|
||||
@dataclass
|
||||
@ -61,6 +63,7 @@ class ContentObject:
|
||||
contentStyle: int
|
||||
contentUrl: Optional[str] = ""
|
||||
title: Optional[str] = ""
|
||||
description: Optional[str] = ""
|
||||
mediaList: Optional[MediaList] = None
|
||||
# 视频号消息
|
||||
finderFeed: Optional[FinderFeed] = None
|
||||
|
@ -3,6 +3,7 @@ import json
|
||||
import shutil
|
||||
import threading
|
||||
import time
|
||||
from typing import Tuple
|
||||
|
||||
import xmltodict
|
||||
|
||||
@ -38,6 +39,31 @@ def get_img_css(size: int) -> str:
|
||||
return f'width:5rem;height:5rem;float:left;margin-bottom:0.2rem;margin-right:0.2rem;{img_style}'
|
||||
|
||||
|
||||
def is_music_msg(msg: MomentMsg) -> bool:
|
||||
"""判断一个msg是否为音乐分享
|
||||
"""
|
||||
if msg.timelineObject.ContentObject and msg.timelineObject.ContentObject.mediaList and msg.timelineObject.ContentObject.mediaList.media:
|
||||
media = msg.timelineObject.ContentObject.mediaList.media[0]
|
||||
if media.type == '5':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_music_info(msg: MomentMsg) -> Tuple[str, str, str]:
|
||||
"""获取音乐标题,演唱者,音乐源
|
||||
"""
|
||||
title = ""
|
||||
musician = ""
|
||||
src = ""
|
||||
if msg.timelineObject.ContentObject and msg.timelineObject.ContentObject.mediaList and msg.timelineObject.ContentObject.mediaList.media:
|
||||
media = msg.timelineObject.ContentObject.mediaList.media[0]
|
||||
title = media.title
|
||||
musician = media.description
|
||||
if media.url:
|
||||
src = media.url.text
|
||||
return title, musician, src
|
||||
|
||||
|
||||
class HtmlExporter(threading.Thread):
|
||||
|
||||
def __init__(self, gui: 'Gui', dir_name: str, contacts_map: dict[str, Contact], begin_date: datetime.date,
|
||||
@ -85,12 +111,12 @@ class HtmlExporter(threading.Thread):
|
||||
self.file.write(self.html_head)
|
||||
# 加一天
|
||||
end_date = self.end_date + datetime.timedelta(days=1)
|
||||
begin_time = time.mktime(datetime.datetime(self.begin_date.year, self.begin_date.month, self.begin_date.day).timetuple())
|
||||
begin_time = time.mktime(
|
||||
datetime.datetime(self.begin_date.year, self.begin_date.month, self.begin_date.day).timetuple())
|
||||
end_time = time.mktime(datetime.datetime(end_date.year, end_date.month, end_date.day).timetuple())
|
||||
|
||||
self.gui.video_decrypter.decrypt_videos(self, self.begin_date, end_date, self.dir_name, self.convert_video)
|
||||
|
||||
|
||||
message_datas = sns_db.get_messages_in_time(begin_time, end_time)
|
||||
for index, message_data in enumerate(message_datas):
|
||||
if not self.stop_flag:
|
||||
@ -157,6 +183,26 @@ class HtmlExporter(threading.Thread):
|
||||
html += f' <div class ="text" >{msg.timelineObject.ContentObject.title}</div>\n'
|
||||
html += ' </div >\n'
|
||||
html += ' </a>\n'
|
||||
# 音乐
|
||||
elif is_music_msg(msg):
|
||||
|
||||
title, musician, src = get_music_info(msg)
|
||||
html += f' <a href="{msg.timelineObject.ContentObject.contentUrl}" target="_blank">\n'
|
||||
html += ' <div class ="music_link" >\n'
|
||||
html += ' <div class ="music_des" >\n'
|
||||
if images:
|
||||
thumb_path, image_path = images[0]
|
||||
html += f' <img src = "{thumb_path}"/>\n'
|
||||
html += ' <div class = "music_title_musician">\n'
|
||||
html += f' <div class = "music_title">{title}</div>\n'
|
||||
html += f' <div class = "music_musician">{musician}</div>\n'
|
||||
html += ' </div>\n'
|
||||
html += ' </div>\n'
|
||||
html += f' <audio class = "music_audio" controls>'
|
||||
html += f' <source src="{src}" type="audio/mpeg">'
|
||||
html += f' </audio>'
|
||||
html += ' </div >\n'
|
||||
html += ' </a>\n'
|
||||
# 视频号
|
||||
elif msg.timelineObject.ContentObject.finderFeed:
|
||||
html += f' <div style="width:10rem; overflow:hidden">\n'
|
||||
|
@ -27,6 +27,23 @@ class ImageExporter:
|
||||
file.write(response.content)
|
||||
return f'{img_type}s/{file_name}.jpg'
|
||||
|
||||
@staticmethod
|
||||
def get_image_thumb_and_url(media_item) -> Tuple[str, str]:
|
||||
""" 获取图片的缩略图与大图的链接
|
||||
"""
|
||||
thumb = None
|
||||
url = None
|
||||
# 普通图片
|
||||
if media_item.type == "2":
|
||||
thumb = media_item.thumb.text
|
||||
url = media_item.url.text
|
||||
# 微信音乐
|
||||
if media_item.type == "5":
|
||||
thumb = media_item.thumb.text
|
||||
url = media_item.thumb.text
|
||||
|
||||
return thumb, url
|
||||
|
||||
def get_images(self, msg: MomentMsg, download_pic: int) -> list[Tuple]:
|
||||
""" 获取一条朋友圈的全部图像, 返回值是一个元组列表
|
||||
[(缩略图路径,原图路径),(缩略图路径,原图路径)]
|
||||
@ -37,13 +54,14 @@ class ImageExporter:
|
||||
|
||||
media = msg.timelineObject.ContentObject.mediaList.media
|
||||
for media_item in media:
|
||||
if media_item.type == "2":
|
||||
thumb, url = self.get_image_thumb_and_url(media_item)
|
||||
if thumb and url:
|
||||
if download_pic:
|
||||
thumb_path = self.save_image(media_item.thumb.text, 'thumb')
|
||||
image_path = self.save_image(media_item.url.text, 'image')
|
||||
thumb_path = self.save_image(thumb, 'thumb')
|
||||
image_path = self.save_image(url, 'image')
|
||||
else:
|
||||
thumb_path = media_item.thumb.text
|
||||
image_path = media_item.url.text
|
||||
thumb_path = thumb
|
||||
image_path = url
|
||||
if thumb_path and image_path:
|
||||
results.append((thumb_path, image_path))
|
||||
|
||||
|
@ -60,6 +60,15 @@ padding-top:0.2rem;
|
||||
.out_link {background-color:#F7F7F7 ;font-size:0.7rem ;width:95% ;color:#41454D ;overflow: hidden; cursor:pointer;}
|
||||
.out_link img{width:2.5rem ;height:2.5rem ;margin:0.5rem 0.5rem ;float: left;}
|
||||
|
||||
.music_link {background-color:#F7F7F7 ;font-size:0.7rem ;width:95% ;color:#41454D ;overflow: hidden; cursor:pointer; display: flex; flex-direction:column}
|
||||
.music_des {width:100%;display: flex;}
|
||||
.music_title_musician {width:100%;margin-left: 1.5rem;display: flex;flex-direction:column}
|
||||
.music_title {font-size:1.0rem;margin-top: 0.5rem;}
|
||||
.music_musician {font-size:0.85rem;margin-top: 0.5rem;}
|
||||
.music_link img{width:4rem ;height:4rem ;margin:0.2rem 0.2rem ;float: left;}
|
||||
.music_audio {height: 1.5rem; width: 95%;}
|
||||
|
||||
|
||||
.text{float: left;margin-top: 1.1rem;width:80% ;}
|
||||
.pl{margin-top:0.5rem ;font-size:0.6rem ;color:#80858c ;clear: both;}
|
||||
.pl span{display:inline-block ;width:2rem ;}
|
||||
|
Loading…
Reference in New Issue
Block a user