您在PPStream上完整看下来的影片在本地是有缓存的,缓存文件大小1G。Windows下的缓存文件名是ppsds.pgf,位置可以通过打开PPStream,在“工具–>选项–>点播服务–>缓存文件管理”里面找到。Ubuntu下的缓存文件名是ems.cache,位置为“~/.pps/datacache”,注意‘~’代表家目录,“.pps”是一个隐藏的文件夹。您最近观看的影片都能从缓存文件中提取成能够正常播放的视频,下面分别介绍Windows和Ubuntu下提取视频的办法。
Windows下可从http://download.csdn.net/source/1292410下载压缩包,里面详细介绍了提取影片的办法,不仅有现成的可执行程序,还有源代码供您参考,这里就不做详细介绍了。
Linux下也是参考了Windows上的实现方式,不过不是用的C语言,而是用Python代码实现的,由于Python具有很好的跨平台性,所以如果您发现Windows上的C语言提取程序已经失效了,不妨也试试下面这段Python代码。
import re
import sys
import imp
import codecs
import logging
import os
import mmap
from struct import unpack_from
from urllib.parse import unquote
from itertools import takewhile
logging.basicConfig(level=logging.INFO,
format='%(levelname)s %(lineno)d | %(message)s',
datefmt='%H:%M:%S')
MAXCACHEIDX=1024**3
INFOBLOCK=1616
DATABLOCK=1024**2*2
BLOCK=INFOBLOCK+DATABLOCK
def _getFileInfo(cacheFile):
ret={}
with open(cacheFile,'rb') as f:
mf=mmap.mmap(f.fileno(),0,prot=mmap.PROT_READ)
firstIDX=1073656324
idx=firstIDX
cnt=0
while idx < MAXCACHEIDX:
# get 20bytes hash string
hashid=''.join('%X'%x for x in mf[idx+4:idx+4+20])
# get number of idxpost items
nr_idxpos=unpack_from('<L',mf,idx+4+20)[0]
# get idxpost items
idxpos=unpack_from('<%s'%('L'*nr_idxpos,),mf,idx+0x11c)
# get filename
dataBgn=idx+8476
cnt+=1
n=''.join(chr(x) for x in takewhile(lambda x:x!=0,mf[dataBgn:dataBgn+96]))
n=unquote(n,'gbk')
if n in ret:
assert ret[n]['hashid']==hashid
assert ret[n]['blkall']==blkall
idx+=9500
continue
# get blocks number
blkall=unpack_from('<L',mf,idx+8476+0x104)[0]
logging.debug('%d) find filename %s at %d',cnt,n,dataBgn)
logging.debug('\thash=%s',hashid)
logging.debug('\tnr_idxpos=%d',nr_idxpos)
assert nr_idxpos==len(idxpos)
logging.debug('\t all blks should be %d',blkall)
if idxpos.count(0)==0 and len(idxpos)==blkall:
logging.debug('\t-=-=- this is a complete file list -=-=-')
ret[n]={'filename':n,'blks':None,'blkall':blkall,'hashid':hashid}
idx+=9500
mf.close()
return ret
def _check(cacheFile,info,firstBlock=1836):
tmpblks={}
for k,v in info.items():
tmpblks[v['hashid']]=[0 for _ in range(v['blkall'])]
with open(cacheFile,'rb') as f:
f=mmap.mmap(f.fileno(),0,prot=mmap.PROT_READ)
blkno=unpack_from('!B',f,firstBlock+60)[0]+ unpack_from('!B',f,firstBlock+61)[0]*0xff
idx= firstBlock
while 0< idx < 1068274747:
blkno=unpack_from('!B',f,idx+60)[0]+ unpack_from('!B',f,idx+61)[0]*0x100
assert blkno<509
tmpchk=''.join('%X'%x for x in f[idx+40:idx+60])
try:
tmpblks[tmpchk][blkno]=idx
except:
logging.debug('%s at %d not in !',tmpchk,idx)
idx+=BLOCK
f.close()
for k,v in info.items():
if v['hashid'] in tmpblks:
v['blks']=tmpblks[v['hashid']]
else:
logging.debug('%s %s have no data!',k,v['hashid'])
v['blks']=[]
return info
def _extractFile(cacheFile,info,outDir):
ofilename=os.path.join(outDir,os.path.basename(info['filename']))
with open(cacheFile,'rb') as f:
f=mmap.mmap(f.fileno(),0,prot=mmap.PROT_READ)
logging.info('writting to file %s ...',ofilename)
with open(ofilename,'wb') as fo:
cnt=0
for blkidx in info['blks']:
if blkidx!=0:
fo.write(f[blkidx+INFOBLOCK:blkidx+INFOBLOCK+DATABLOCK])
cnt+=1
else:
pass
logging.info('file %s wrote. total %d blocks, %d bytes',ofilename,cnt,cnt*DATABLOCK)
f.close()
def extractFileFromPPStreamCache(cacheFile):
info=_getFileInfo(cacheFile)
info=_check(cacheFile,info)
cnt=0
fs=[]
for k,v in info.items():
cnt+=1
logging.info('%d) %s %d/%d',cnt,k,len([ x for x in v['blks'] if x!=0]),v['blkall'])
fs.append(k)
if len(info)>0:
try:
x=int(input('choose file to extract (1-%d):'%(len(info),)))
except ValueError:
logging.info('input invaild!')
else:
if 0< x <=len(info):
_extractFile(cacheFile,info[fs[x-1]],'/tmp/')
if __name__=='__main__':
imp.reload(sys)
sys.setdefaultencoding('utf-8')
extractFileFromPPStreamCache(os.path.expanduser('~/.pps/datacache/ems.cache'))
logging.debug('done')
input('press ENTER to exit ...')
将上面这段Python代码保存为名为PPStream.py的文件,由于Python对格式的要求极其严格,请确保您拷贝过去的代码没有破坏上面的对齐或者缩进模式。倘若Python解析器提示格式错误,请尝试用TAB缩进符号重新按照原来的格式缩进。如果您想在Windows上尝试用以上代码来提取视频,请将倒数第三行代码里面的路径该为您的Windows上ppsds.pgf缓存文件存放的路径。
光有上面的代码保存的PPStream.py文件,没有Python解析器,代码是没法执行的。所有如果您系统上没有Python解析器,那就需要安装python,注意得安装3.0以后版本,这里我们在Ubuntu上安装python3,执行如下命令:
sudo apt-get install python3
安装好以后,cd到PPStream.py存放的目录,执行如下命名:
python3 PPStream.py
终端会显示缓存文件中已有的视频列表,提示您选择要提取的视频。按提示输入以后,提取成功的视频会保存在“/tmp”目录下。
如果您拷贝的python仍有问题,可以在下面留言向我索取PPStream.py文件。
除非注明,文章均为CppLive 编程在线原创,转载请注明出处,谢谢。




大大!请给我一份PPStream.py!
另外PPStream.py应该放在哪里?
一执行就这样了!
dibing@dibing-Aspire-4935:~/.pps/datacache$ python3 PPStream.py
File “PPStream.py”, line 1
1. import re
^
IndentationError: unexpected indent
好的,邮件已发送,请查收附件~
刚刚下载试用了一下。
同样,注释掉了124行。
但程序运行起来,就死在那里了。
有pdf格式文件的说明文档吗?
你是用的是Linux下的PPStream吗?版本是0.1.1678吗?你观看过视频以后,是否发现如下路径“~/.pps/datacache/ems.cache”的这个ems.cache文件?还有请务必使用 python3 执行以上脚本。也可能是脚本格式的问题,我将脚本原文件以附件的形式邮件发给你了,请注意查收。
博主太厉害了!刚开了个新博,看到你这么有技术性的文章……表示压力很大 > <
我要向博主学习阿!!
PS: 我用的是Lubuntu,我要将123行的 sys.setdefaultencoding('utf-8') 删除了才OK,原因不明。因为终端弹出错误提示:
File "PPStream.py", line 123, in
sys.setdefaultencoding(‘utf-8’)
AttributeError: ‘module’ object has no attribute ‘setdefaultencoding’
你的这个问题在Ubuntu上没有出现过,如果去掉倒数第五行倒是会出现。在Winows上有跟你同样的问题,我也不大清楚原因,难道Lubuntu默认字符编码跟Windows一样都不是utf-8?
我的ubuntu12.04删除了第123行后:
dibing@dibing-Aspire-4935:~/.pps/datacache$ python3 PPStream.py Traceback (most recent call last):
File “PPStream.py”, line 123, in
extractFileFromPPStreamCache(os.path.expanduser(‘~/.pps/datacache/ems.cache’))
File “PPStream.py”, line 104, in extractFileFromPPStreamCache
info=_getFileInfo(cacheFile)
File “PPStream.py”, line 43, in _getFileInfo
assert ret[n][‘hashid’]==hashid
AssertionError
呵呵 多谢捧场 😛