QQ群聊天记录文件分割
嗯,如题 是个蛋疼物
目前QQ的聊天记录导出功能很让人郁闷
三种聊天记录格式的导出
1 TXT 没图
2 BAK 只能再导入QQ使用
3 MHT 有图有字,缺点是一旦聊天记录很多,文件体积就会很大,几乎所有的工具都不能正常打开
单纯的把MHT转换成HTML也不行,因为HTML也很大,加上图片之类的资源 也会卡死
于是只能切开显示,处理思路很简单,就是超大的文本文件,按行顺序处理,把图片解码存入文件,然后分割HTML内容
代码如下 只支持单个QQ群导出记录
<?php ini_set('pcre.backtrack_limit',1000000); $is_table_end = false ; $page = 0 ;$contents = ''; $output_zip = './test.zip'; #判断输入文件 if(!file_exists($argv[1])) { echo 'There isn\'t have this file.'; exit; } #建立归档文件 默认为 make_output_target($output_zip); $handle = fopen($argv[1], "rb"); #分段处理 do { $contents .=fread($handle,124416);#wtf $contents = mht_process($contents,$output_zip); } while (!feof($handle)); #主体数据处理 function mht_process($contents,$output_zip){ Global $is_table_end; Global $page; $zip = new ZipArchive; if ($zip->open($output_zip,ZIPARCHIVE::CREATE) !== TRUE) { echo 'create image failed'; exit; } #判断非图片消息部分是否处理完毕 if(false === $is_table_end) { $html_head = '<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>QQ Message</title><style type="text/css">body{font-size:12px; line-height:22px; margin:2px;}td{font-size:12px; line-height:22px;}</style></head><body><table width=100% cellspacing=0>'; $html_foot = '</table></body></html>'; #判断消息部分是否完毕 只处理图片部分 if(false !== strpos($contents,$html_foot)) { $is_table_end = true; } $r = preg_match_all ('|<tr.*?\</tr\>|ims', $contents , $matches ,PREG_OFFSET_CAPTURE); if($r) { $matches = array_chunk($matches[0],200); foreach($matches as $key=>$val) { $arr = array_column($val,0); array_walk( $arr , function(&$v, $k) use ($zip) { $v = preg_replace('|<IMG src="{(\S)(\S)(\S+).dat|ims','<IMG src="../images/$1/$2/{$1$2$3.dat',$v); }); $zip->addFromString('messages/'.sprintf("%08d", $page+$key).'.html' ,$html_head . implode('',$arr).'<td> <H1><a href="./'.sprintf("%08d", $page+$key-1).'.html">Prev page</a></h1> <H1><a href="./'.sprintf("%08d", $page+$key+1).'.html">Next page</a></h1></td>'.$html_foot); } $page += $key; $pos = end($val); $contents = substr($contents,bcadd($pos[1],strlen($pos[0]),0)); } else { $contents = ''; } } #处理图片部分 if(true === $is_table_end) { #图片数据匹配 $r = preg_match_all ('|Content-Type:image.*?:base64.*?Content-Location:(.*?)\.dat(.*?)(?:------=_)|ims', $contents , $matches ,PREG_OFFSET_CAPTURE | PREG_SET_ORDER); if($r) { //$matches = array_chunk($matches[0],200); $result = array(); foreach($matches as $key=>$val){ $result = array('name'=>$val[1][0],'contents'=>$val[2][0]); $dir = 'images/'. substr($result['name'],1,1) .'/' . substr($result['name'],2,1) .'/'.$result['name'] . '.dat'; #写入图片表情文件到硬盘 $zip->addFromString($dir,base64_decode(trim($result['contents']))); $result = array(); } $result = array(); $contents = substr($contents,$val[0][1]); } else { $contents = ''; } } $zip->close(); #剩余部分返回 下一次处理拼接数据 return $contents; } #建立保存目标 function make_output_target($output='./test.zip') { $zip = new ZipArchive; if ($zip->open($output,ZIPARCHIVE::CREATE) !== TRUE) { echo 'create images directory failed'; exit; } $zip->addEmptyDir('images'); $tmp = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'); array_walk($tmp,function($val,$key) use ($tmp,$zip) { $base_path = 'images/'.$val; $zip->addEmptyDir($base_path); array_walk($tmp,function($val,$key) use ($tmp,$zip,$base_path) { $zip->addEmptyDir($base_path.'/'.$val); }); }); $zip->addEmptyDir('messages'); $zip->close(); return 0; }
使用方法
1 "php.exe" cli.php input.mht > log.txt 2 pause
生成ZIP之后 可以用winmount来挂载查看 无需解压很方便