python使用正则将QQ聊天记录转换为Html

一、需求

提取qq聊天记录中的所有图片并保存在指定的文件夹。

二、知识要点

  • 大文件的流式匹配。re[1]、mmap[2]
  • 命令行进度条。tqdm[3]
  • 构建简单的命令行工具。click[4]
  • python多进程异步IO。multiprocessing.apply_async()[5]

三、全部代码

import re
import os
import sys
import mmap
import base64
import  multiprocessing as m
import click
from tqdm import tqdm


def  get_images(mhtFilepath):
    with open(mhtFilepath,'r+') as f:   #打开模式必须为读写模式
        data = mmap.mmap(f.fileno(), 0) #内存映射,防止文件过大,内存溢出
        pattern=re.compile(rb'Content-Type:image/(.*?)\r\nContent-Transfer-Encoding.*?\r\nContent-Location:{(.*?)}.dat\r\n\r\n(.*?)\r\n\r\n',re.DOTALL) #正则匹配图片后缀名、base64编码的图片数据、文件ID
        return pattern.finditer(data)   #finditer返回迭代对象,findall返回list(内存占用太大)

def write_to_image(imgOutputpath,strFileName,strContent,strSuffix):
    with open(imgOutputpath + "/" + strFileName + "." + strSuffix,'wb') as f:
        f.write(base64.b64decode(strContent))

@click.command()
@click.argument('mht_filename', type=click.Path(exists=True))
@click.option('--image_output_path','-o','image_output_path', prompt=True,help='image output path')
def get_images_from_mht(mht_filename,image_output_path):
    '''从mht文件中提取图片'''
    if not os.path.exists(image_output_path):
        click.echo('{}路径不存在'.format(image_output_path))
        code=input('是否创建文件?(Y/N)')
        if code.strip().lower()=='y':
            try:
                os.makedirs(image_output_path)
            except Exception as e:
                click.echo('无法创建目录',e)
                sys.exit(0)
        else:
            sys.exit(0)
    else:
        cwd=os.getcwd()
        try:
            os.makedirs(cwd+'/images')
        except Exception as e:
            click.echo('无法创建目录',e)
            sys.exit(0)
    click.echo('正在从{}提取图片,请稍后...'.format(click.format_filename(mht_filename)))
    pool = m.Pool(processes=m.cpu_count())  #创建进程池
    d = get_images(mht_filename)
    for item in tqdm(d,unit='张'):
        suffix = item.group(1).decode('utf-8')
        filename = item.group(2).decode('utf-8')
        content = item.group(3).decode('utf-8')
        pool.apply_async(write_to_image, (image_output_path,filename,content,suffix,)) #异步io写入文件,节省时间
    pool.close()
    pool.join()
    click.echo('提取完成,图片保存在{}'.format(click.format_filename(image_output_path)))


if __name__=='__main__':
    get_images_from_mht()

四、使用方法

第三步代码保存到getImgsFromMht.py,在cmd或powershell中执行python getImgsFromMht.py --help
获取图片:python getImgsFromMht.py -d 图片保存路径 mht文件路径

五、参考资料


  1. Python中re的match、search、findall、finditer区别 ↩

  2. 来源于"Stack Overflow"----how-do-i-re-search-or-re-match-on-a-whole-file-without-reading-it-all-into-memory ↩

  3. tqdm参考文档 ↩

  4. click参考文档 ↩

  5. 多进程copy文件 ↩

你可能感兴趣的:(python使用正则将QQ聊天记录转换为Html)