跳转到内容

python

安装python

python下载地址,安装时一定要选择Add Python to PATH(否则命令行无法识别python命令)

下载python后运行

python --version

查看python是否安装成功

创建python文件,name.py

在文件所在的文件夹下cmd,运行命令python name.py运行python代码

运行时会没反应,如不打印print输出内容

运行type name.py查看是否有乱码,如果有乱码说明文件不是utf-8,在文件头部添加如下内容

# -*- coding: utf-8 -*-

结合使用,网站批量下载图片,根据数组图片名称顺序修改文件夹内图片名称

如将abc45635.jpg修改为1.jpg

谷歌浏览器添加扩展工具Download All Images 3.1.0.crx(在工具文件夹),批量下载漫画图片

下载后的图片名不是按顺序排列的且图片名一长串abc45635.jpg

在控制台找到按顺序的图片代码右键 -> copy -> copy Element,写个函数处理一下把图片的名字按顺序生成个数组,代码如下:

html
<script>
  
const htmlString = `
<div class="comic-contain"><div class="comic-contain__item" data-pid="0" data-index="0">
                    <img class="lazy-read" src="blob:https://www.manhua55.com/9c6bd774-3382-47b6-9fce-14762995ad18" data-src="/static/upload2/book/id/335002/30864568/90bedc3892ee731e5d5310159f9460c4_zb.webp" referrerpolicy="no-referrer">
                </div><div class="comic-contain__item" data-pid="1" data-index="1">
                    <img class="lazy-read" src="blob:https://www.manhua55.com/f2aff142-aa14-47a8-950b-82837808adaa" data-src="/static/upload2/book/id/335002/30864568/d418ccc34c18f554655b760d3525e56c_zb.webp" referrerpolicy="no-referrer">
                </div>`;

// 创建一个临时DOM元素来解析HTML字符串
const tempDiv = document.createElement('div');
tempDiv.innerHTML = htmlString;

// 获取所有img元素
const imgElements = tempDiv.querySelectorAll('img[src^="blob:https://www.manhua55.com/"]');

// 提取blob:后面的字符串并生成数组
const blobIds = Array.from(imgElements).map(img => {
    const src = img.getAttribute('src');
    // 提取blob:https://www.manhua55.com/后面的部分
    return src.replace('blob:https://www.manhua55.com/', '');
});

console.log(blobIds); // 输出: ["9c6bd774-3382-47b6-9fce-14762995ad18"]

</script>

在浏览器运行,通过console获取数组,右键复制数组,替换到python文件里,运行python自动改名完成

之后写个重命名的python文件,文件和图片放在同一个文件夹下,如以下代码放在G盘text文件夹下

把图片名数组替换以下targets = ['a', 'b', 'c'] # 需要完全匹配的字符串

在文件夹目录上输入cmd,然后运行python name.py

python
# -*- coding: utf-8 -*-

print("===== 调试信息 =====")

import os

def rename_files_by_exact_match(folder_path, target_strings):
    
    files = os.listdir(folder_path)
    print("找到文件列表:", files)
    
    for filename in files:
        name_part, ext = os.path.splitext(filename)
        print(f"\n检查文件: {filename} → 分离为: ('{name_part}', '{ext}')")
        
        if name_part in target_strings:
            index = target_strings.index(name_part)
            new_name = f"{index}{ext}"
            old_path = os.path.join(folder_path, filename)
            new_path = os.path.join(folder_path, new_name)
            
            print(f"匹配成功! 将重命名为: {new_name}")
            os.rename(old_path, new_path)
        else:
            print("未匹配目标字符串")
    
    print("\n=== 处理完成 ===")

# 使用示例
folder = r"G:\text"  # 替换为你的实际路径
targets = ['a', 'b', 'c']  # 需要完全匹配的字符串

print("===== 调试信息 =====")
print("文件夹是否存在:", os.path.exists(folder))
rename_files_by_exact_match(folder, targets)
input("按回车退出...")

创建test.py文件在该目录下cmd用python test.py运行无反应,在其他目录(之前成功运行python的目录)中自动复制了此test.py文件,在该文件夹下运行python正常,解决方案如下

造成此原因是有多个python.exe文件,造成干扰导致运行python时运行的不是正常的python优先级被打乱

在有问题的文件夹下cmd输入

where python

如果显示有两个python.exe文件,判断哪个是正常的python通常带Microsoft\WindowsApps的是应用商店自己下载的python,如果不能判断可以让ai辅助判断,然后运行如下代码删除此项

del "C:\Users\Afand\AppData\Local\Microsoft\WindowsApps\python.exe"

之后再运行如下代码

where python
python -c "print('Hello')"

能正常输出了即可

运行python文件,实现输入文件名,把包含该文件名的所有子文件都移动到新创建的同名文件夹下

实现在当前目录下运行python文件,输入要移动的txt文件名称,将当前目录所有文件夹内的子文件包含该文件名的txt文件都移动到根据输入的名称创建的文件夹下

如输入“测试”,则当前文件夹下所有子文件包含“测试”的文件都移动到新创建的测试文件夹下,具体代码如下

import os
import shutil
from pathlib import Path

def organize_files_recursive():
    keyword = input("请输入要搜索的文件名关键字:").strip()
    
    if not keyword:
        return
    
    target_folder = Path(keyword)
    if not target_folder.exists():
        target_folder.mkdir()
    
    current_dir = Path('.').resolve()
    target_path_resolved = target_folder.resolve()
    
    moved_files = []
    
    print(f"当前目录: {current_dir}")
    print(f"目标文件夹: {target_path_resolved}")
    print("-" * 50)
    
    for root, dirs, files in os.walk('.', topdown=True):
        # 将root转换为绝对路径进行比较
        root_abs = Path(root).resolve()
        
        # 使用绝对路径比较,确保只跳过目标文件夹
        if root_abs == target_path_resolved:
            print(f"跳过的确实是目标文件夹: {root_abs}")
            # 从遍历列表中移除,避免遍历目标文件夹内部
            if root in dirs:
                dirs.remove(root)
            continue
        
        for file in files:
            if keyword in file:
                source_abs = root_abs / file
                
                # 再次确认不是目标文件夹内的文件
                try:
                    # 检查文件是否已经在目标文件夹中
                    if source_abs.parent == target_path_resolved:
                        print(f"跳过已在目标文件夹中的文件: {file}")
                        continue
                except:
                    pass
                
                target_file = target_folder / file
                
                # 处理重名
                counter = 1
                while target_file.exists():
                    name, ext = os.path.splitext(file)
                    target_file = target_folder / f"{name}_{counter}{ext}"
                    counter += 1
                
                try:
                    shutil.move(str(source_abs), str(target_file))
                    # 显示相对路径
                    rel_source = source_abs.relative_to(current_dir) if source_abs.is_relative_to(current_dir) else source_abs
                    moved_files.append(str(rel_source))
                    print(f"✓ 已移动: {rel_source}")
                except Exception as e:
                    print(f"✗ 移动失败 {file}: {e}")
    
    if moved_files:
        print(f"\n✓ 完成!移动了 {len(moved_files)} 个文件")
    else:
        print(f"\n⚠ 未找到文件")

if __name__ == "__main__":
    organize_files_recursive()
    input("\n按回车退出")

运行python文件,实现输入多个文件名如(文件名1,文件名2...),分别把包含文件名的所有子文件都移动到和py所在文件夹的同级名为chuli的文件夹下的新创建的同名文件夹下

在对应py文件的文件夹下cmd,然后输入python 文件名.py运行该文件,根据提示输入要操作的文件名

import os
import shutil
from pathlib import Path

def organize_files_recursive():
    # 输入多个关键字,用逗号分隔
    keywords_input = input("请输入要搜索的文件名关键字(多个关键字请用逗号分隔,如:文件1,文件2,文件3):").strip()
    
    if not keywords_input:
        return
    
    # 分割关键字并去除空格
    keywords = [kw.strip() for kw in keywords_input.split(',') if kw.strip()]
    
    if not keywords:
        return
    
    # 获取py文件所在目录的上一级目录(同级目录)
    script_dir = Path(__file__).parent.resolve()
    chuli_dir = script_dir.parent / 'chuli'  # py文件所在文件夹的同级文件夹中的chuli文件夹
    
    # 创建chuli文件夹(如果不存在)
    if not chuli_dir.exists():
        chuli_dir.mkdir(parents=True)
        print(f"创建文件夹: {chuli_dir}")
    
    # 为每个关键字创建对应的文件夹并移动文件
    for keyword in keywords:
        print(f"\n{'='*60}")
        print(f"正在处理关键字: {keyword}")
        print(f"{'='*60}")
        
        # 在chuli文件夹中创建关键字文件夹
        target_folder = chuli_dir / keyword
        if not target_folder.exists():
            target_folder.mkdir()
        
        current_dir = Path('.').resolve()
        target_path_resolved = target_folder.resolve()
        
        moved_files = []
        
        print(f"当前工作目录: {current_dir}")
        print(f"目标文件夹: {target_path_resolved}")
        print("-" * 50)
        
        for root, dirs, files in os.walk('.', topdown=True):
            # 将root转换为绝对路径进行比较
            root_abs = Path(root).resolve()
            
            # 跳过chuli文件夹(避免重复遍历)
            if root_abs == chuli_dir.resolve() or chuli_dir.resolve() in root_abs.parents:
                if root in dirs:
                    dirs.clear()
                continue
            
            # 跳过所有关键字对应的文件夹(避免重复遍历)
            skip_folders = [(chuli_dir / kw).resolve() for kw in keywords if (chuli_dir / kw).exists()]
            if root_abs in skip_folders:
                # 从遍历列表中移除该文件夹的子目录
                if root in dirs:
                    dirs.clear()  # 清空子目录列表,避免遍历
                continue
            
            for file in files:
                if keyword in file:
                    source_abs = root_abs / file
                    
                    # 检查文件是否已经在目标文件夹中
                    if source_abs.parent == target_path_resolved:
                        print(f"跳过已在目标文件夹中的文件: {file}")
                        continue
                    
                    target_file = target_folder / file
                    
                    # 处理重名
                    counter = 1
                    while target_file.exists():
                        name, ext = os.path.splitext(file)
                        target_file = target_folder / f"{name}_{counter}{ext}"
                        counter += 1
                    
                    try:
                        shutil.move(str(source_abs), str(target_file))
                        # 显示相对路径
                        rel_source = source_abs.relative_to(current_dir) if source_abs.is_relative_to(current_dir) else source_abs
                        moved_files.append(str(rel_source))
                        print(f"✓ 已移动: {rel_source}")
                    except Exception as e:
                        print(f"✗ 移动失败 {file}: {e}")
        
        if moved_files:
            print(f"\n✓ 关键字 '{keyword}' 完成!移动了 {len(moved_files)} 个文件")
            print(f"  文件已移动到: {target_folder}")
        else:
            print(f"\n⚠ 未找到包含 '{keyword}' 的文件")
    
    print(f"\n{'='*60}")
    print(f"所有关键字处理完成!")
    print(f"所有文件已移动到: {chuli_dir}")

if __name__ == "__main__":
    organize_files_recursive()
    input("\n按回车退出")

修改当前文件夹下的子文件夹的名称,如将《书名》或2019-0-1《书名》或《书名》这是一本书或【新】书名【读书站】或2018-08书名或2018-08 书名或02 书名或2.书名或02书名或www.edo.cn - 书名或①书名修改成书名,其中子文件夹下的文件内容不变

创建一个rename_folders.py文件,内容如下,在该文件的目录上输入cmd回车,再输入python rename_folders.py运行该文件,按提示操作即可,此代码遇到重复的文件名即不做处理,如文件夹下有子文件夹书名和子文件夹《书名》,则《书名》会被保留,方便自己做相同文件的处理(把保留的文件移动到其他文件夹下处理再移动回来去重)

import os
import re

def process_folder_name(name):
    """根据规则处理文件夹名称"""
    original_name = name
    
    # 1. 优先提取《》内部的内容(如果存在)
    match = re.search(r'《([^》]*)》', name)
    if match:
        name = match.group(1)
    
    # 2. 删除所有【xxx】格式的内容
    name = re.sub(r'【[^】]*】', '', name)
    
    # 3. 去除开头的各种前缀(日期、数字编号、特殊符号等)
    #    3.1 去除开头的日期格式:YYYY-MM 或 YYYY-M 或 YYYY年MM月 等
    name = re.sub(r'^\d{4}[-年]\d{1,2}[月]?\s*', '', name)
    #    3.2 去除开头的数字范围:如 "1-4." 或 "1-4、" 等
    name = re.sub(r'^\d+[-~]\d+[\.、]?\s*', '', name)
    #    3.3 去除开头的数字 + 点 + 可选空格:如 "1." 或 "01." 或 "1. "
    name = re.sub(r'^\d+(?:\.|、)\s*', '', name)
    #    3.4 去除开头的数字 + 可选空格(无点):如 "01 " 或 "1 " 或 "02"(数字直接连文字)
    name = re.sub(r'^\d+\s*', '', name)
    #    3.5 去除开头的带圈数字:① ② ③ 等
    name = re.sub(r'^[①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳]\s*', '', name)
    #    3.6 去除开头的罗马数字(简单版):I. II. III. 等
    name = re.sub(r'^[IVXLCDM]+\.\s*', '', name)
    
    # 4. 去除开头的网站/来源标识(如 "ePUBw.COM - "、"xxx.com - " 等)
    #    匹配模式:任意字符(不含换行)+ 空格 + 减号 + 空格
    name = re.sub(r'^[A-Za-z0-9\.]+(\s*-\s*|\s+-\s+)', '', name)
    #    更通用的匹配:xxx.xxx - 或 xxx - 格式
    name = re.sub(r'^[A-Za-z0-9\.]+\s*-\s*', '', name)
    
    # 5. 处理 "xxx_中文描述" 格式(如果没有书名号的情况)
    if '_' in name and not match:
        name = name.split('_')[0]
    
    # 6. 处理括号内的描述(如 (珍藏版))-> 删除
    name = re.sub(r'\([^)]*\)', '', name)
    name = re.sub(r'([^)]*)', '', name)
    
    # 7. 处理套装描述
    name = re.sub(r'套装[共\d册]*', '', name)
    
    # 8. 处理 + 号(保留,但清理两边空格)
    name = re.sub(r'\s*\+\s*', '+', name)
    
    # 9. 删除首尾空格
    name = name.strip()
    
    # 10. 删除多余的空格(连续多个空格变成单个)
    name = re.sub(r'\s+', ' ', name)
    
    # 如果处理后是空字符串,恢复原名称
    if not name:
        name = original_name
    
    return name

def rename_folders():
    """处理当前py文件所在文件夹下的子文件夹名称"""
    
    current_dir = os.path.dirname(os.path.abspath(__file__))
    
    print(f"工作目录: {current_dir}")
    print("-" * 60)
    
    try:
        items = os.listdir(current_dir)
        folders = [item for item in items 
                   if os.path.isdir(os.path.join(current_dir, item))]
    except PermissionError:
        print("错误:没有权限读取当前目录")
        return
    
    if not folders:
        print("当前目录下没有子文件夹")
        return
    
    # 预览修改
    print("预览修改(不执行实际重命名):")
    print("-" * 60)
    
    changes = []
    for folder in folders:
        new_name = process_folder_name(folder)
        if new_name != folder:
            changes.append((folder, new_name))
            print(f"原名称: {folder}")
            print(f"新名称: {new_name}")
            print("-" * 40)
    
    if not changes:
        print("没有需要修改的文件夹名称")
        return
    
    print(f"\n共发现 {len(changes)} 个文件夹需要重命名")
    confirm = input("是否执行重命名?(y/n): ").strip().lower()
    
    if confirm != 'y':
        print("已取消重命名操作")
        return
    
    print("\n开始重命名...")
    success_count = 0
    for old_name, new_name in changes:
        old_path = os.path.join(current_dir, old_name)
        new_path = os.path.join(current_dir, new_name)
        
        if os.path.exists(new_path):
            print(f"跳过 {old_name} -> {new_name} (目标已存在)")
            continue
        
        try:
            os.rename(old_path, new_path)
            print(f"✓ {old_name} -> {new_name}")
            success_count += 1
        except Exception as e:
            print(f"✗ 重命名失败 {old_name}: {e}")
    
    print(f"\n完成!成功重命名 {success_count}/{len(changes)} 个文件夹")

if __name__ == "__main__":
    rename_folders()

如果不需要去重,需要把书名和《书名》文件夹合并成书名,并且重复文件自动修改名字的代码如下

import os
import re
import shutil

def process_folder_name(name):
    """根据规则处理文件夹名称"""
    original_name = name
    
    # 1. 优先提取《》内部的内容(如果存在)
    match = re.search(r'《([^》]*)》', name)
    if match:
        name = match.group(1)
    
    # 2. 删除所有【xxx】格式的内容
    name = re.sub(r'【[^】]*】', '', name)
    
    # 3. 去除开头的各种前缀(日期、数字编号、特殊符号等)
    #    3.1 去除开头的日期格式:YYYY-MM 或 YYYY-M 或 YYYY年MM月 等
    name = re.sub(r'^\d{4}[-年]\d{1,2}[月]?\s*', '', name)
    #    3.2 去除开头的数字范围:如 "1-4." 或 "1-4、" 等
    name = re.sub(r'^\d+[-~]\d+[\.、]?\s*', '', name)
    #    3.3 去除开头的数字 + 点 + 可选空格:如 "1." 或 "01." 或 "1. "
    name = re.sub(r'^\d+(?:\.|、)\s*', '', name)
    #    3.4 去除开头的数字 + 可选空格(无点):如 "01 " 或 "1 " 或 "02"(数字直接连文字)
    name = re.sub(r'^\d+\s*', '', name)
    #    3.5 去除开头的带圈数字:① ② ③ 等
    name = re.sub(r'^[①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳]\s*', '', name)
    #    3.6 去除开头的罗马数字(简单版):I. II. III. 等
    name = re.sub(r'^[IVXLCDM]+\.\s*', '', name)
    
    # 4. 去除开头的网站/来源标识(如 "ePUBw.COM - "、"xxx.com - " 等)
    name = re.sub(r'^[A-Za-z0-9\.]+(\s*-\s*|\s+-\s+)', '', name)
    name = re.sub(r'^[A-Za-z0-9\.]+\s*-\s*', '', name)
    
    # 5. 处理 "xxx_中文描述" 格式(如果没有书名号的情况)
    if '_' in name and not match:
        name = name.split('_')[0]
    
    # 6. 处理括号内的描述(如 (珍藏版))-> 删除
    name = re.sub(r'\([^)]*\)', '', name)
    name = re.sub(r'([^)]*)', '', name)
    
    # 7. 处理套装描述
    name = re.sub(r'套装[共\d册]*', '', name)
    
    # 8. 处理 + 号(保留,但清理两边空格)
    name = re.sub(r'\s*\+\s*', '+', name)
    
    # 9. 删除首尾空格
    name = name.strip()
    
    # 10. 删除多余的空格(连续多个空格变成单个)
    name = re.sub(r'\s+', ' ', name)
    
    # 如果处理后是空字符串,恢复原名称
    if not name:
        name = original_name
    
    return name

def merge_folders(source_path, target_path):
    """将源文件夹的内容合并到目标文件夹"""
    try:
        # 遍历源文件夹中的所有内容
        for item in os.listdir(source_path):
            source_item = os.path.join(source_path, item)
            target_item = os.path.join(target_path, item)
            
            # 如果是文件,直接移动
            if os.path.isfile(source_item):
                # 如果目标文件已存在,添加后缀避免覆盖
                if os.path.exists(target_item):
                    base, ext = os.path.splitext(item)
                    counter = 1
                    while os.path.exists(os.path.join(target_path, f"{base}_{counter}{ext}")):
                        counter += 1
                    target_item = os.path.join(target_path, f"{base}_{counter}{ext}")
                shutil.move(source_item, target_item)
            
            # 如果是文件夹,递归合并
            elif os.path.isdir(source_item):
                if os.path.exists(target_item):
                    # 递归合并子文件夹
                    merge_folders(source_item, target_item)
                else:
                    # 直接移动整个文件夹
                    shutil.move(source_item, target_item)
        
        # 删除空的源文件夹
        if os.path.exists(source_path) and not os.listdir(source_path):
            os.rmdir(source_path)
        else:
            # 如果不是空的,尝试强制删除(理论上上面已经移完所有内容)
            try:
                os.rmdir(source_path)
            except OSError:
                print(f"  警告:无法删除 {source_path},可能还有残留文件")
        
        return True
    except Exception as e:
        print(f"  合并失败:{e}")
        return False

def rename_folders():
    """处理当前py文件所在文件夹下的子文件夹名称"""
    
    current_dir = os.path.dirname(os.path.abspath(__file__))
    
    print(f"工作目录: {current_dir}")
    print("-" * 60)
    
    try:
        items = os.listdir(current_dir)
        folders = [item for item in items 
                   if os.path.isdir(os.path.join(current_dir, item))]
    except PermissionError:
        print("错误:没有权限读取当前目录")
        return
    
    if not folders:
        print("当前目录下没有子文件夹")
        return
    
    # 第一步:预览所有修改
    print("预览修改:")
    print("-" * 60)
    
    changes = []  # 存储 (原名称, 新名称, 是否需要合并)
    merge_pairs = []  # 存储需要合并的 (源文件夹, 目标文件夹)
    
    for folder in folders:
        new_name = process_folder_name(folder)
        if new_name != folder:
            changes.append((folder, new_name))
            print(f"原名称: {folder}")
            print(f"新名称: {new_name}")
            print("-" * 40)
    
    if not changes:
        print("没有需要修改的文件夹名称")
        return
    
    # 第二步:检查并建立需要合并的映射关系
    # 构建原名称到新名称的映射
    rename_map = {old: new for old, new in changes}
    
    # 查找冲突:新名称已存在(且不是重命名自身)
    for old_name, new_name in changes:
        if new_name in folders and new_name != old_name:
            # 需要将 old_name 合并到已存在的 new_name
            merge_pairs.append((old_name, new_name))
            print(f"\n⚠️ 检测到冲突:")
            print(f"  源文件夹: {old_name}")
            print(f"  目标文件夹: {new_name} (已存在)")
            print(f"  将合并内容并删除 {old_name}")
    
    # 第三步:询问用户确认
    print(f"\n共发现 {len(changes)} 个文件夹需要处理")
    if merge_pairs:
        print(f"其中 {len(merge_pairs)} 个需要合并到已存在的文件夹")
    confirm = input("\n是否执行操作?(y/n): ").strip().lower()
    
    if confirm != 'y':
        print("已取消操作")
        return
    
    # 第四步:执行合并操作
    print("\n开始处理...")
    success_merge = 0
    for source_name, target_name in merge_pairs:
        source_path = os.path.join(current_dir, source_name)
        target_path = os.path.join(current_dir, target_name)
        
        print(f"\n合并: {source_name} -> {target_name}")
        
        if not os.path.exists(source_path):
            print(f"  跳过:源文件夹不存在")
            continue
        if not os.path.exists(target_path):
            print(f"  跳过:目标文件夹不存在")
            continue
        
        if merge_folders(source_path, target_path):
            print(f"  ✓ 合并成功")
            success_merge += 1
        else:
            print(f"  ✗ 合并失败")
    
    # 第五步:执行重命名(只处理没有冲突的)
    print("\n执行重命名...")
    success_rename = 0
    for old_name, new_name in changes:
        # 跳过已经被合并的文件夹
        if any(old_name == pair[0] for pair in merge_pairs):
            continue
        
        old_path = os.path.join(current_dir, old_name)
        new_path = os.path.join(current_dir, new_name)
        
        # 检查目标是否已存在(再次确认)
        if os.path.exists(new_path):
            print(f"跳过 {old_name} -> {new_name} (目标已存在,需要手动处理)")
            continue
        
        try:
            os.rename(old_path, new_path)
            print(f"✓ {old_name} -> {new_name}")
            success_rename += 1
        except Exception as e:
            print(f"✗ 重命名失败 {old_name}: {e}")
    
    print(f"\n完成!")
    print(f"  - 成功合并: {success_merge}/{len(merge_pairs)} 个文件夹")
    print(f"  - 成功重命名: {success_rename}/{len(changes) - len(merge_pairs)} 个文件夹")

if __name__ == "__main__":
    rename_folders()

简单处理网文文件标题

先生成当前文件夹下的文件标题文件用powershell Get-ChildItem -Name > 11.txt

然后创建个first_title.py,在当前文件夹运行,输入要处理的文件名11.txt

再创建个second_title.py,在当前文件夹运行,输入要处理的文件名output_清理后的书名.txt,后输出的valid_titles.txt为大致处理好的标题名可以直接用整理文件的py批量输入使用,输出的invalid_titles.txt可进行二次处理

其中代码如下:

first_title.py
import os
import re

def clean_title(title: str) -> str:
    """
    清理书名,删除指定模式和符号
    """
    # 保存原始标题用于最后的处理
    original_title = title
    
    # 1. 首先处理文件名中的".txt"扩展名
    if title.endswith('.txt'):
        title = title[:-4]
    elif '.' in title:
        title = title.rsplit('.', 1)[0]
    
    # 2. 删除"作者:"或"作家:"及其后面的所有内容(使用字符串分割)
    if '作者:' in title:
        title = title.split('作者:')[0]
    if '作者:' in title:
        title = title.split('作者:')[0]
    if '作家:' in title:
        title = title.split('作家:')[0]
    if '作家:' in title:
        title = title.split('作家:')[0]
    
    # 3. 删除各种括号及其内部的所有内容
    brackets = [
        ('[', ']'), ('[', ']'), ('【', '】'), ('(', ')'), 
        ('(', ')'), ('〖', '〗'), ('『', '』'), ('「', '」'), 
        ('{', '}'), ('<', '>'), ('《', '》')
    ]
    for left, right in brackets:
        pattern = f'\\{left}[^{right}]*\\{right}'
        title = re.sub(pattern, '', title)
    
    # 4. 删除《以及该符号前的所有内容
    if '《' in title:
        title = title.split('《', 1)[-1]
    
    # 5. 删除》以及该符号后的所有内容
    if '》' in title:
        title = title.split('》', 1)[0]
    
    # 6. 删除"."以及该符号后的所有内容
    if '.' in title:
        title = title.split('.', 1)[0]
    if '。' in title:
        title = title.split('。', 1)[0]
    
    # 7. 删除各种格式的GL、BL、BG标签
    tags_to_remove = [
        'GL', 'Gl', 'gL', 'gl',  # GL的各种写法
        'BL', 'Bl', 'bL', 'bl',  # BL的各种写法
        'BG', 'Bg', 'bG', 'bg',  # BG的各种写法
        '百合', 'abo', 'ABO', 'np', 'NP',  # 其他标签
    ]
    for tag in tags_to_remove:
        title = title.replace(tag, '')
    
    # 8. 删除by及其后面的所有内容
    if 'by' in title.lower():
        by_index = title.lower().find('by')
        title = title[:by_index]
    if 'By' in title:
        title = title.split('By')[0]
    if 'BY' in title:
        title = title.split('BY')[0]
    
    # 9. 删除可能残留的括号内容
    title = re.sub(r'[((][^))]*[))]', '', title)
    
    # 10. 删除"(番外完)"等标记
    title = re.sub(r'[((]番外.*?[))]', '', title)
    title = re.sub(r'[((]完结.*?[))]', '', title)
    
    # 11. 删除首尾多余的空格和符号
    title = title.strip()
    title = title.strip(',,。!?、::;;')
    
    # 12. 清理连续的空格
    title = re.sub(r'\s+', ' ', title)
    title = title.strip()
    
    # 13. 删除末尾的数字(如章节号)
    title = re.sub(r'\s*\d+\s*$', '', title)
    
    # 14. 如果处理后为空,尝试从原标题提取
    if not title or len(title) < 2:
        # 提取中文字符
        chinese_chars = re.findall(r'[\u4e00-\u9fff]+', original_title)
        if chinese_chars:
            # 取最长的中文连续字符串
            title = max(chinese_chars, key=len)
        else:
            return "无法识别"
    
    return title

def read_file_with_encoding(file_path):
    """尝试多种编码读取文件"""
    encodings_to_try = ['utf-8', 'gbk', 'gb2312', 'gb18030', 'utf-16']
    
    for enc in encodings_to_try:
        try:
            with open(file_path, 'r', encoding=enc) as f:
                lines = [line.strip() for line in f if line.strip()]
            print(f"成功使用编码: {enc}")
            return lines
        except (UnicodeDecodeError, LookupError):
            continue
    
    # 最后尝试二进制读取并忽略错误
    try:
        with open(file_path, 'rb') as f:
            raw_data = f.read()
            content = raw_data.decode('utf-8', errors='ignore')
            lines = [line.strip() for line in content.splitlines() if line.strip()]
            print("使用UTF-8(忽略错误)读取成功")
            return lines
    except:
        pass
    
    return []

def process_file():
    """
    处理文件:读取、清理标题、去重、输出新文件
    """
    # 获取脚本所在目录
    base_dir = os.path.dirname(os.path.abspath(__file__))
    
    # 输入文件名
    input_name = input("请输入要处理的文件名(如 11.txt):").strip()
    input_path = os.path.join(base_dir, input_name)
    
    if not os.path.exists(input_path):
        print(f"错误:文件 {input_path} 不存在,请检查文件名。")
        return
    
    # 读取文件内容
    lines = read_file_with_encoding(input_path)
    
    if not lines:
        print("无法读取文件内容,请检查文件格式。")
        return
    
    print(f"\n共读取到 {len(lines)} 行内容")
    print("="*60)
    
    # 处理每一行
    cleaned_titles = []
    
    for i, line in enumerate(lines, 1):
        original = line
        cleaned = clean_title(line)
        
        # 只保存有效的书名
        if cleaned and cleaned != "无法识别" and len(cleaned) >= 2:
            cleaned_titles.append(cleaned)
            print(f"{i}. 原: {original}")
            print(f"   新: {cleaned}")
            print("-" * 40)
        else:
            print(f"{i}. 跳过无效内容: {original}")
            print("-" * 40)
    
    if not cleaned_titles:
        print("\n警告:没有提取到有效的书名!")
        return
    
    # 去重(保持第一次出现的顺序)
    unique_titles = []
    seen = set()
    for title in cleaned_titles:
        if title not in seen:
            unique_titles.append(title)
            seen.add(title)
    
    print(f"\n去重前: {len(cleaned_titles)} 个书名")
    print(f"去重后: {len(unique_titles)} 个唯一书名")
    
    # 输出到新文件
    output_name = "output_清理后的书名.txt"
    output_path = os.path.join(base_dir, output_name)
    
    with open(output_path, 'w', encoding='utf-8') as f:
        for title in unique_titles:
            f.write(title + '\n')
    
    print(f"\n{'='*60}")
    print(f"处理完成!")
    print(f"结果已保存至:{output_path}")
    print(f"共处理 {len(lines)} 行,成功提取 {len(cleaned_titles)} 个有效书名,去重后剩余 {len(unique_titles)} 个")
    print(f"{'='*60}")
    
    # 显示最终结果
    print("\n最终去重后的书名列表:")
    for i, title in enumerate(unique_titles, 1):
        print(f"{i:2d}. {title}")

if __name__ == "__main__":
    process_file()
second_title.py
import os
import re

def is_valid_title(title: str) -> bool:
    """
    检查标题是否符合规则:
    标题中间不含有空格、-(短横线)、-(全角短横线)、+(加号)、
    _(下划线)、@(at符号)、冒号(中英文)、单引号(中英文)、双引号(中英文)
    """
    # 定义不允许出现的符号
    invalid_patterns = [
        r'\s',           # 空格
        r'-',            # 短横线(半角)
        r'-',           # 短横线(全角)
        r'\+',           # 加号(需要转义)
        r'_',            # 下划线
        r'@',            # at符号
        r':',           # 中文冒号
        r':',            # 英文冒号
        r'‘',            # 中文左单引号
        r'’',            # 中文右单引号
        r'`',            # 反引号
        r"'",            # 英文单引号
        r'"',            # 英文双引号
        r'“',            # 中文左双引号
        r'”',            # 中文右双引号
    ]
    
    for pattern in invalid_patterns:
        if re.search(pattern, title):
            return False
    return True

def process_file():
    """
    处理文件:筛选符合和不符合规则的标题
    """
    # 获取脚本所在目录
    base_dir = os.path.dirname(os.path.abspath(__file__))
    
    # 输入文件名
    input_name = input("请输入要处理的文件名(如 output_清理后的书名.txt):").strip()
    input_path = os.path.join(base_dir, input_name)
    
    if not os.path.exists(input_path):
        print(f"错误:文件 {input_path} 不存在,请检查文件名。")
        return
    
    # 尝试读取文件(支持多种编码)
    lines = []
    encodings_to_try = ['utf-8', 'gbk', 'gb2312', 'gb18030']
    
    for enc in encodings_to_try:
        try:
            with open(input_path, 'r', encoding=enc) as f:
                lines = [line.strip() for line in f if line.strip()]
            print(f"成功使用编码: {enc}")
            break
        except (UnicodeDecodeError, LookupError):
            continue
    
    if not lines:
        # 最后尝试忽略错误
        try:
            with open(input_path, 'rb') as f:
                content = f.read().decode('utf-8', errors='ignore')
                lines = [line.strip() for line in content.splitlines() if line.strip()]
            print("使用UTF-8(忽略错误)读取成功")
        except:
            print("无法读取文件,请检查文件格式。")
            return
    
    print(f"\n共读取到 {len(lines)} 行内容")
    print("="*60)
    
    # 分类标题
    valid_titles = []      # 符合规则的标题
    invalid_titles = []    # 不符合规则的标题
    
    for line in lines:
        if is_valid_title(line):
            valid_titles.append(line)
            print(f"✓ 符合规则: {line}")
        else:
            invalid_titles.append(line)
            print(f"✗ 不符合规则: {line}")
    
    print("="*60)
    
    # 处理符合规则的标题:按长度从长到短排序
    valid_titles.sort(key=lambda x: len(x), reverse=True)
    
    # 用英文逗号分隔,不换行
    valid_output = ','.join(valid_titles)
    
    # 不符合规则的标题:保持原格式,每个标题换一行
    invalid_output = '\n'.join(invalid_titles)
    
    # 输出符合规则的标题文件
    valid_output_name = "valid_titles.txt"
    valid_output_path = os.path.join(base_dir, valid_output_name)
    with open(valid_output_path, 'w', encoding='utf-8') as f:
        f.write(valid_output)
    
    # 输出不符合规则的标题文件
    invalid_output_name = "invalid_titles.txt"
    invalid_output_path = os.path.join(base_dir, invalid_output_name)
    with open(invalid_output_path, 'w', encoding='utf-8') as f:
        f.write(invalid_output)
    
    # 输出统计信息
    print(f"\n处理完成!")
    print(f"="*60)
    print(f"总标题数: {len(lines)}")
    print(f"符合规则的标题数: {len(valid_titles)} (已按长度从长到短排序)")
    print(f"不符合规则的标题数: {len(invalid_titles)} (保持原格式)")
    print(f"="*60)
    print(f"符合规则的标题已保存至: {valid_output_path}")
    print(f"不符合规则的标题已保存至: {invalid_output_path}")
    print(f"="*60)
    
    # 显示符合规则的标题预览
    if valid_titles:
        print("\n符合规则的标题(按长度从长到短):")
        for i, title in enumerate(valid_titles, 1):
            print(f"{i:2d}. {title} (长度: {len(title)})")
        print(f"\n逗号分隔格式:")
        print(valid_output)
    
    # 显示不符合规则的标题预览
    if invalid_titles:
        print(f"\n不符合规则的标题(共{len(invalid_titles)}个):")
        for i, title in enumerate(invalid_titles, 1):
            print(f"{i:2d}. {title}")

if __name__ == "__main__":
    process_file()

暴力破解压缩包密码

创建unzip_tool.py文件代码如下,确保电脑装了7-zip压缩app,运行代码直接按提示输入密码长度,可以在代码中添加常用密码,先使用常用密码破解,不成功使用暴力密码破解

根据提示输入密码长度,输入密码规则,输入起始密码或不填从头开始,然后破解即可。中通想停止可以用ctrl+c停止破解,会显示已经破解的进度和密码,可以记录当前破解密码,下次从此密码开始破解。

import os
import sys
import subprocess
import itertools
import time
import signal
from pathlib import Path

# 全局变量用于控制停止
stop_flag = False
current_testing_password = ""

def signal_handler(sig, frame):
    """处理Ctrl+C信号"""
    global stop_flag, current_testing_password
    stop_flag = True
    print(f"\n\n用户请求停止... 当前正在测试密码: {current_testing_password}")
    print("正在保存进度并退出...")

def find_7zip():
    """查找7-Zip安装路径"""
    common_paths = [
        r"C:\Program Files\7-Zip\7z.exe",
        r"C:\Program Files (x86)\7-Zip\7z.exe",
        r"D:\Program Files\7-Zip\7z.exe",
        r"D:\Program Files (x86)\7-Zip\7z.exe",
    ]
    
    for path in common_paths:
        if Path(path).exists():
            return path
    
    try:
        result = subprocess.run(['where', '7z'], capture_output=True, text=True)
        if result.returncode == 0:
            return result.stdout.strip().split('\n')[0]
    except:
        pass
    
    return None

def parse_password_rule(rule_input, specified_length):
    """
    解析密码规则
    
    规则示例:
    - "0" : 纯数字
    - "a" : 纯小写字母
    - "A" : 纯大写字母
    - "0a" : 数字和小写字母(包括纯数字和纯字母)
    - "0aA" : 数字、大小写字母(包括纯组合)
    - "0aA,.!" : 数字、大小写字母、特殊字符(包括纯组合)
    - "-0a" : 数字和小写字母的混合(排除纯数字和纯字母)
    - "-0aA" : 数字、大小写字母混合(排除纯数字、纯小写、纯大写)
    - "-0aA,.!" : 数字、大小写字母、特殊字符混合(排除纯字符组合)
    """
    # 检查是否为混合模式(排除纯字符组合)
    mixed_mode = False
    if rule_input.startswith('-'):
        mixed_mode = True
        rule_input = rule_input[1:]  # 移除前缀
    
    char_sets = {
        '0': '0123456789',
        'a': 'abcdefghijklmnopqrstuvwxyz',
        'A': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    }
    
    # 收集字符集
    chars = []
    special_chars = []
    selected_types = []  # 记录选择了哪些类型
    
    i = 0
    while i < len(rule_input):
        char = rule_input[i]
        if char in char_sets:
            chars.append(char_sets[char])
            selected_types.append(char)
            i += 1
        else:
            # 收集特殊字符
            special_start = i
            while i < len(rule_input) and rule_input[i] not in '0aA':
                i += 1
            special_chars.append(rule_input[special_start:i])
            if special_chars[-1]:
                selected_types.append('special')
    
    # 合并所有字符集
    all_chars = ''.join(chars)
    if special_chars:
        all_chars += ''.join(special_chars)
    
    # 如果没有选择任何字符集,默认使用数字
    if not all_chars:
        all_chars = '0123456789'
        selected_types = ['0']
        print("未指定字符集,默认使用数字(0-9)")
    
    # 去重并保持顺序
    all_chars = ''.join(sorted(set(all_chars), key=all_chars.index))
    
    return specified_length, all_chars, mixed_mode, selected_types, special_chars

def is_pure_combo(password, selected_types, special_chars):
    """
    检查密码是否为纯字符组合(只包含单一字符集)
    
    Args:
        password: 密码字符串
        selected_types: 选择的类型列表,如 ['0', 'a'] 或 ['0', 'a', 'special']
        special_chars: 特殊字符列表
    """
    if not selected_types or len(selected_types) == 1:
        return True
    
    # 定义各类型的字符集
    type_chars = {
        '0': set('0123456789'),
        'a': set('abcdefghijklmnopqrstuvwxyz'),
        'A': set('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
    }
    
    # 添加特殊字符集
    if special_chars:
        special_set = set(''.join(special_chars))
        type_chars['special'] = special_set
    
    # 找出密码中包含哪些类型的字符
    used_types = set()
    for char in password:
        for pwd_type, char_set in type_chars.items():
            if char in char_set:
                used_types.add(pwd_type)
                break
    
    # 如果只使用了单一类型,则是纯组合
    return len(used_types) == 1

def string_to_index(password, char_set):
    """将密码字符串转换为索引"""
    index = 0
    for char in password:
        index = index * len(char_set) + char_set.index(char)
    return index

def index_to_string(index, length, char_set):
    """将索引转换为密码字符串"""
    password = []
    for i in range(length):
        index, remainder = divmod(index, len(char_set))
        password.append(char_set[remainder])
    return ''.join(reversed(password))

def try_unzip(zip_path, password, extract_dir):
    """尝试用指定密码解压"""
    cmd = [
        seven_zip_path,
        "x",
        str(zip_path),
        f"-o{extract_dir}",
        "-y"
    ]
    
    if password:
        cmd.append(f"-p{password}")
    
    try:
        result = subprocess.run(
            cmd, 
            capture_output=True, 
            text=True, 
            encoding='utf-8',
            errors='ignore',
            timeout=1  # 设置超时1秒
        )
        
        if result.returncode == 0:
            return True, result.stdout
        else:
            return False, result.stderr
    except subprocess.TimeoutExpired:
        return False, "超时"
    except Exception as e:
        return False, str(e)

def brute_force_password(zip_path, length, char_set, extract_dir, mixed_mode, selected_types, special_chars, start_password=None):
    """
    暴力破解密码
    start_password: 起始密码,从该密码开始遍历(包含该密码)
    """
    global stop_flag, current_testing_password
    
    # 计算总组合数和起始索引
    if start_password:
        start_index = string_to_index(start_password, char_set)
        total_combinations_raw = len(char_set) ** length
        remaining_combinations = total_combinations_raw - start_index
        print(f"\n从密码 '{start_password}' 开始遍历")
        print(f"起始索引: {start_index:,}")
        print(f"剩余需要尝试: {remaining_combinations:,} 个密码")
    else:
        start_index = 0
        remaining_combinations = len(char_set) ** length
    
    if mixed_mode:
        print(f"\n开始混合模式暴力破解...")
        print(f"密码长度: {length}")
        print(f"字符集: {char_set}")
        print(f"字符集大小: {len(char_set)}")
        print(f"模式: 只尝试混合密码(排除纯字符组合)")
        print("-" * 50)
    else:
        print(f"\n开始暴力破解...")
        print(f"密码长度: {length}")
        print(f"字符集: {char_set}")
        print(f"字符集大小: {len(char_set)}")
        print(f"总组合数: {remaining_combinations:,}")
        print("-" * 50)
    
    attempts = 0
    start_time = time.time()
    last_print_time = start_time
    total_skipped = 0  # 跳过的纯组合数量
    
    # 从起始索引开始生成密码
    current_index = start_index
    total = len(char_set) ** length
    
    while current_index < total and not stop_flag:
        # 将索引转换为密码
        current_testing_password = index_to_string(current_index, length, char_set)
        
        # 如果是混合模式,过滤掉纯组合
        if mixed_mode and is_pure_combo(current_testing_password, selected_types, special_chars):
            current_index += 1
            total_skipped += 1
            continue
        
        attempts += 1
        
        # 显示进度(每100次或每0.5秒显示一次)
        current_time = time.time()
        if attempts % 100 == 0 or current_time - last_print_time > 0.5:
            elapsed = current_time - start_time
            speed = attempts / elapsed if elapsed > 0 else 0
            percent = ((current_index - start_index + 1) / remaining_combinations) * 100 if remaining_combinations > 0 else 0
            
            if mixed_mode:
                print(f"\r尝试次数: {attempts:,} | 速度: {speed:.0f} 密码/秒 | "
                      f"进度: {percent:.2f}% | 跳过纯组合: {total_skipped:,} | "
                      f"当前测试: {current_testing_password}", end='', flush=True)
            else:
                print(f"\r尝试进度: {percent:.2f}% ({attempts:,}/{remaining_combinations:,}) | "
                      f"速度: {speed:.0f} 密码/秒 | 当前测试: {current_testing_password}", 
                      end='', flush=True)
            last_print_time = current_time
        
        # 尝试解压
        success, output = try_unzip(zip_path, current_testing_password, extract_dir)
        
        if success:
            elapsed = time.time() - start_time
            print(f"\n\n{'='*50}")
            print(f"✓✓✓ 成功!密码正确!✓✓✓")
            print(f"正确密码: {current_testing_password}")
            print(f"尝试次数: {attempts:,}")
            print(f"耗时: {elapsed:.2f} 秒")
            print(f"{'='*50}")
            return current_testing_password
        
        current_index += 1
    
    if stop_flag:
        print(f"\n\n{'='*50}")
        print(f"程序已停止")
        print(f"最后一个测试的密码: {current_testing_password}")
        print(f"已尝试密码数: {attempts:,}")
        print(f"未找到正确密码")
        print(f"{'='*50}")
        return None
    
    elapsed = time.time() - start_time
    print(f"\n\n{'='*50}")
    if mixed_mode:
        print(f"✗ 破解失败!已尝试 {attempts:,} 个混合密码")
    else:
        print(f"✗ 破解失败!已尝试所有 {remaining_combinations:,} 种可能")
    print(f"耗时: {elapsed:.2f} 秒")
    print(f"{'='*50}")
    return None

def smart_brute_force(zip_path, length, char_set, extract_dir, mixed_mode, selected_types, special_chars, start_password=None):
    """
    智能暴力破解(优化版)
    先尝试常见密码,再尝试其他组合
    """
    global stop_flag, current_testing_password
    
    print(f"\n开始智能破解...")
    print(f"密码长度: {length}")
    print(f"字符集: {char_set}")
    if mixed_mode:
        print(f"模式: 混合模式(排除纯字符组合)")
    if start_password:
        print(f"起始密码: {start_password}")
    print("-" * 50)
    
    attempts = 0
    start_time = time.time()
    
    # 1. 先尝试常见弱密码(仅当没有指定起始密码时)
    if not start_password:
        common_passwords = set()
        
        # 纯数字常见密码
        if '0' in selected_types:
            common_passwords.update([
                '1234', '123456', '12345678', '12345', '123', '0000', '1111', '2222',
                '3333', '4444', '5555', '6666', '7777', '8888', '9999', '1212', '1122',
                '0603', '2023', '0201', '8848', '1231', '123123', '111111', '0124', 
                '2795', '5853', '520521', '2024', '0126', '0801', '123456789', '5732', 
                '1314', '1212', '102074', '1115', '1717', '2025', '2026'
            ])
        
        # 包含字母的常见密码
        if 'a' in selected_types or 'A' in selected_types:
            common_passwords.update([
                'admin', 'root', 'user', 'abc', 'abcd', 'abcde', 'abcdef',
                'qwer', 'qwert', 'qwerty', 'asdf', 'asdfg', 'zxcv', 'zxcvb',
                'yms', 'ysm', 'bymltt', 'byhatake', 'baihehuakai', 'amtw', 
                'yurifans', 'HAHA', 'yuri', 'ayue'
            ])
        
        # 混合常见密码
        common_passwords.update([
            'abc123', '123abc', 'admin123', '123admin', 'password', 'pass123',
            'bctt3233', 'bycycy1', 'gn5853', 'manhun3233', 'yy123', 'abcd123'
        ])
        
        # 过滤符合长度和字符集要求的常见密码
        valid_common = []
        for pwd in common_passwords:
            if len(pwd) == length and all(c in char_set for c in pwd):
                # 如果是混合模式,还要确保不是纯组合
                if mixed_mode and is_pure_combo(pwd, selected_types, special_chars):
                    continue
                valid_common.append(pwd)
        
        if valid_common:
            print(f"尝试 {len(valid_common)} 个常见密码...")
            for password in valid_common:
                if stop_flag:
                    break
                attempts += 1
                current_testing_password = password
                print(f"\r尝试 #{attempts}: {password}", end='', flush=True)
                success, _ = try_unzip(zip_path, password, extract_dir)
                if success:
                    elapsed = time.time() - start_time
                    print(f"\n\n{'='*50}")
                    print(f"✓✓✓ 成功!密码正确!✓✓✓")
                    print(f"正确密码: {password}")
                    print(f"尝试次数: {attempts}")
                    print(f"耗时: {elapsed:.2f} 秒")
                    print(f"{'='*50}")
                    return password
        
        if stop_flag:
            print(f"\n\n程序已停止于常见密码阶段")
            return None
        
        print(f"\n\n常见密码未成功,开始完整暴力破解...")
    
    # 2. 如果没有找到,再尝试所有组合
    return brute_force_password(zip_path, length, char_set, extract_dir, 
                                mixed_mode, selected_types, special_chars, start_password)

def get_start_password(length, char_set):
    """
    获取起始密码
    
    Returns:
        起始密码字符串,如果为None表示从头开始
    """
    print("\n" + "="*50)
    print("起始密码设置说明:")
    print("-" * 50)
    print("您可以从指定密码开始遍历,跳过之前的密码")
    print(f"当前密码长度为{length},字符集包含: {char_set}")
    print("示例:")
    print(f"  - 数字密码: 3333, 8888, 9999")
    print(f"  - 字母密码: abcd, xyz, hello")
    print(f"  - 混合密码: abc123, 123abc")
    print("-" * 50)
    print("提示:")
    print("  - 留空或输入0:从头开始遍历")
    print("  - 输入密码:从该密码开始遍历(包含该密码)")
    print("  - 所有密码必须符合长度和字符集要求")
    print("="*50)
    
    while True:
        start_input = input("\n请输入起始密码(留空从头开始): ").strip()
        
        if not start_input or start_input == '0':
            return None
        
        # 检查长度
        if len(start_input) != length:
            print(f"错误:密码长度必须为{length}位!")
            continue
        
        # 检查字符集
        invalid_chars = [c for c in start_input if c not in char_set]
        if invalid_chars:
            print(f"错误:密码包含非法字符 {invalid_chars}")
            print(f"允许的字符集: {char_set}")
            continue
        
        return start_input

def main():
    """主函数"""
    global seven_zip_path, stop_flag
    
    # 注册信号处理函数
    signal.signal(signal.SIGINT, signal_handler)
    
    current_dir = Path(__file__).parent
    
    # 查找7-Zip
    print("正在查找7-Zip...")
    seven_zip_path = find_7zip()
    
    if not seven_zip_path:
        print("错误:找不到7-Zip!")
        input("按回车键退出...")
        return
    
    print(f"✓ 找到7-Zip: {seven_zip_path}")
    print("-" * 50)
    
    # 显示当前目录下的压缩文件
    zip_files = list(current_dir.glob('*.zip')) + \
                list(current_dir.glob('*.rar')) + \
                list(current_dir.glob('*.7z'))
    
    if zip_files:
        print("当前目录下的压缩文件:")
        for f in zip_files:
            print(f"  - {f.name}")
    else:
        print("当前目录下没有找到压缩文件")
    print("-" * 50)
    
    # 输入压缩包名称
    while True:
        zip_name = input("\n请输入压缩包名称(如:书11.zip): ").strip()
        
        if not zip_name:
            print("请输入文件名!")
            continue
        
        zip_path = current_dir / zip_name
        
        if not zip_path.exists():
            print(f"错误:找不到文件 {zip_name}")
            retry = input("是否重新输入?(y/n): ").strip().lower()
            if retry != 'y':
                print("程序结束")
                return
            continue
        break
    
    # 输入密码长度
    while True:
        try:
            password_length = int(input("请输入密码位数(如:4): ").strip())
            if password_length > 0:
                break
            else:
                print("密码位数必须大于0!")
        except ValueError:
            print("请输入有效的数字!")
    
    # 输入密码规则
    print("\n" + "="*60)
    print("密码规则说明:")
    print("-" * 60)
    print("基本规则:")
    print("  - 输入 '0' 表示包含数字 0-9")
    print("  - 输入 'a' 表示包含小写字母 a-z")
    print("  - 输入 'A' 表示包含大写字母 A-Z")
    print("  - 直接输入其他字符表示包含这些字符(如:,.!@#)")
    print("-" * 60)
    print("使用示例:")
    print("  '0'          : 纯数字")
    print("  'a'          : 纯小写字母")
    print("  'A'          : 纯大写字母")
    print("  '0a'         : 数字+小写字母(包括纯数字和纯字母)")
    print("  '0aA'        : 数字+大小写字母(包括纯组合)")
    print("  '0aA,.!'     : 数字+大小写字母+特殊字符(包括纯组合)")
    print("  '-0a'        : 数字+小写字母的混合(排除纯数字和纯字母)")
    print("  '-0aA'       : 数字+大小写字母混合(排除纯数字、纯小写、纯大写)")
    print("  '-0aA,.!'    : 数字+大小写字母+特殊字符混合(排除纯字符组合)")
    print("="*60)
    
    rule_input = input("\n请输入密码规则: ").strip()
    if not rule_input:
        rule_input = '0'
        print("未输入规则,默认使用纯数字(0-9)")
    
    # 解析规则
    length, char_set, mixed_mode, selected_types, special_chars = parse_password_rule(rule_input, password_length)
    
    # 获取起始密码
    start_password = get_start_password(length, char_set)
    if start_password:
        print(f"将从密码 '{start_password}' 开始遍历")
    
    # 确认信息
    print("\n" + "="*50)
    print("破解配置确认:")
    print(f"压缩包: {zip_name}")
    print(f"密码长度: {length}")
    print(f"字符集: {char_set}")
    print(f"字符集大小: {len(char_set)}")
    print(f"密码类型: {'混合模式(排除纯字符组合)' if mixed_mode else '包含纯字符组合'}")
    print(f"包含的字符类型: {', '.join(selected_types)}")
    if start_password:
        print(f"起始密码: {start_password}")
    else:
        print(f"起始密码: 从头开始")
    
    total_combinations = len(char_set) ** length
    if mixed_mode:
        print(f"总组合数(混合模式): 需要实时计算(会过滤纯组合)")
        print(f"原始总组合数: {total_combinations:,}")
    else:
        print(f"总组合数: {total_combinations:,}")
    
    if total_combinations > 10000000 and not mixed_mode and not start_password:  # 超过1千万且从头开始
        print("\n⚠️ 警告:组合数较大,可能需要很长时间!")
        print(f"预计时间: {total_combinations / 10000 / 60:.1f} 分钟(按每秒1万次计算)")
    
    print("="*50)
    
    confirm = input("\n是否开始破解?(y/n): ").strip().lower()
    if confirm != 'y':
        print("程序结束")
        return
    
    # 开始破解
    extract_dir = current_dir  # 直接解压到当前目录
    print(f"\n解压目标目录: {extract_dir}")
    print("提示:按 Ctrl+C 可以随时停止程序,并显示当前进度\n")
    
    # 选择破解模式
    use_smart = input("\n是否使用智能破解(先尝试常见密码)?(y/n,默认y): ").strip().lower()
    if use_smart == 'n':
        password = brute_force_password(zip_path, password_length, char_set, extract_dir, 
                                        mixed_mode, selected_types, special_chars, start_password)
    else:
        password = smart_brute_force(zip_path, password_length, char_set, extract_dir, 
                                    mixed_mode, selected_types, special_chars, start_password)
    
    if password:
        print(f"\n✓✓✓ 破解成功!密码是: {password}")
        print(f"✓ 文件已解压到: {extract_dir}")
    elif stop_flag:
        print(f"\n程序已停止")
        if current_testing_password:
            print(f"最后一个测试的密码: {current_testing_password}")
    else:
        print(f"\n✗ 破解失败,未找到正确密码")
    
    print("\n程序结束")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n程序被用户中断")
    except Exception as e:
        print(f"\n程序出错: {e}")
    finally:
        input("\n按回车键退出...")