-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
功能需求:过滤重复图片 #245
功能需求:过滤重复图片 #245
Changes from all commits
6c7a132
5896d7a
cb9bb3a
2065f01
2482f3c
ef8f458
11019c9
90cb0fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -1035,3 +1035,62 @@ def try_mark_photo_skip_and_log(self, photo: JmPhotoDetail, at_least_image_count | |||||||||||||||||||||||||||||||||||||||||||||||||||||
@field_cache() # 单例 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
def build(cls, option: JmOption) -> 'JmOptionPlugin': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return super().build(option) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
class DeleteDuplicatedFilesPlugin(JmOptionPlugin): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
https://github.com/hect0x7/JMComic-Crawler-Python/issues/244 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
plugin_key = 'delete_duplicated_files' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
@classmethod | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
def calculate_md5(cls, file_path): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
import hashlib | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""计算文件的MD5哈希值""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
hash_md5 = hashlib.md5() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
with open(file_path, "rb") as f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
for chunk in iter(lambda: f.read(4096), b""): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
hash_md5.update(chunk) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return hash_md5.hexdigest() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1046
to
+1055
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure proper error handling in Consider adding error handling for file operations to prevent the application from crashing if the file is inaccessible or corrupt. Here's a suggested modification: - with open(file_path, "rb") as f:
+ try:
+ with open(file_path, "rb") as f:
+ for chunk in iter(lambda: f.read(4096), b""):
+ hash_md5.update(chunk)
+ except IOError as e:
+ print(f"Error reading file {file_path}: {e}")
+ return None Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
@classmethod | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
def find_duplicate_files(cls, root_folder): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""递归读取文件夹下所有文件并计算MD5出现次数""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
from collections import defaultdict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
md5_dict = defaultdict(list) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
for root, _, files in os.walk(root_folder): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
for file in files: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
file_path = os.path.join(root, file) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
file_md5 = cls.calculate_md5(file_path) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
md5_dict[file_md5].append(file_path) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
return md5_dict | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1057
to
+1070
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Optimize file handling in Consider using - import os
+ from pathlib import Path
- for root, _, files in os.walk(root_folder):
+ for file_path in Path(root_folder).rglob('*'):
- file_path = os.path.join(root, file)
- file_md5 = cls.calculate_md5(file_path)
+ file_md5 = cls.calculate_md5(str(file_path)) Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
def invoke(self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
limit, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
album=None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
downloader=None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
delete_original_file=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
**kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if album is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.delete_original_file = delete_original_file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
# 获取到下载本子所在根目录 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
root_folder = self.option.dir_rule.decide_album_root_dir(album) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.find_duplicated_files_and_delete(limit, root_folder, album) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
def find_duplicated_files_and_delete(self, limit: int, root_folder: str, album: Optional[JmAlbumDetail] = None): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
md5_dict = self.find_duplicate_files(root_folder) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
# 打印MD5出现次数大于等于limit的文件 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
for md5, paths in md5_dict.items(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
if len(paths) >= limit: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
prefix = '' if album is None else f'({album.album_id}) ' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
message = [prefix + f'MD5: {md5} 出现次数: {len(paths)}'] + \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
[f' {path}' for path in paths] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.log('\n'.join(message)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
self.execute_deletion(paths) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1040
to
+1096
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Review the The
- with open(file_path, "rb") as f:
+ try:
+ with open(file_path, "rb") as f:
+ for chunk in iter(lambda: f.read(4096), b""):
+ hash_md5.update(chunk)
+ except IOError as e:
+ print(f"Error reading file {file_path}: {e}")
+ return None
- import os
+ from pathlib import Path
- for root, _, files in os.walk(root_folder):
+ for file_path in Path(root_folder).rglob('*'):
- file_path = os.path.join(root, file)
- file_md5 = cls.calculate_md5(file_path)
+ file_md5 = cls.calculate_md5(str(file_path))
- if album is None:
+ if album is None:
+ self.log("No album provided, skipping duplicate file deletion.")
+ return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace star imports with explicit imports to improve code clarity and maintainability.