二、数据清洗,对广告信息说不

在上一章,我们已经拿到了40G的数据,如何分析这些文档,是最主要的目标。由于网站在ppt文档中暴力插入了广告链接,删掉这些与内容无关的信息就是文档解析的第一步。

本文主要是两部分信息:

  • 文档脏数据的定位与删除;
  • MSOffice接口简单介绍;

1、“脏数据”都有什么?

就目标站点来说,往文档中插的信息无外乎这三类:

  • 文档描述信息;
  • 文本框连接;
  • 广告页;
文档描述信息
文本框广告
单页广告

其中,文档描述信息不影响此次内容分析,暂不处理。剩余两类数据的清洗逻辑很简单,将在下一章介绍。

2、数据清洗的准备工作

就PowerPoint来说,已经提供了删除页面内文本框和删除Slide的接口。熟悉VBA的朋友(容易 暴露年龄)很容易在宏编辑中组织代码,进而在C++中实现完整逻辑。这次,我选择用python 实现,所有源码详见Git

同时,我把VB代码在Git中也保留了一份,很方便您在宏编辑器中调试。

2.1、关于MSOffice Interface Reference

这部分的知识比较老,现在用的也不多。如果您刚接触,可以看我早先前在CSDN上的博 客——《北塔教你做插件》。如果只是查询接口,可以通过一下两个办法:

方法1、MSOffice2010 帮助文件

为什么不是其他版本?因为只有这个版本的帮助文件中提供了“开发人员参考”,点击“搜索”中的类型就可以找到。

Office2010 帮助

帮助文档提供的信息还是比较丰富的,除了接口说明还有很多例子,方便理解各个对象间的关系,是帮助理解、提高效率的利器。

Shape详细信息

方法2、MSO 接口声明
我在Git中保存了MSO和MSPPT的接口声明,详见MSPPT_QuickReference目录

如果您对VBA已经有些了解,且所使用的语言不是 C++的前提下,通过这两个文档查询接口与定义类型还是很方便的。比如,在Python中通过win32Com调用,所需的查询工作就可以在这两个文档中解决。

准备工作就写到这,如果您还不太懂也没关系,进入下一章,我带您用python调用MSO接口,完成这40G文档的数据清洗。

3、PPT文件的数据清洗

创建COfficeAdapter的目的,就是为了封装MSO接口,以实现文件打开、操作和关闭等行为。为数据清洗和文档快照提供支持。

源码如下:

#!/usr/bin/python
# -*- coding: gbk -*-

'''''
对MSOffice COM接口的封装,简单实现文件打开、操作和关闭等行为。
为数据清洗和快照提供支持。
'''

import win32com  
from win32com.client import Dispatch, constants  
import os

msoTrue = -1

class COfficeAdapter():
    def __init__(self ):
        print "init"
        try:
            self.m_App = win32com.client.Dispatch('PowerPoint.Application')
            self.m_App.Visible = 1
        except BaseException:
            print "init Exception!!"
        #隐式加载为0 ,显式加载为1

    def __del__(self):
        print "__del__"
        try:
            self.m_App.Quit()
        except BaseException:
            print "Quit Exception!!"


    def OpenDoc(self, oPath):
        oRet = False
        if os.path.exists(oPath):
            oPath = oPath.lower()
            oNameSplit = os.path.splitext(oPath)
            if (oNameSplit[1] == ".ppt" or oNameSplit[1] == ".pptx"):
                try:
                    self.m_Doc = self.m_App.Presentations.Open(oPath)
                    oRet = True
                except BaseException:
                    print "OpenDoc Exception!!"

        return oRet

    def SaveDoc(self, newfilename=None):
        if newfilename:       
            self.m_Doc.SaveAs(newfilename)                  
        else:   
            oRet = self.m_Doc.Save()
            print "save:" ,oRet

    def CloseDoc(self):
        #print self.m_Doc.Saved
        try:
            self.m_Doc.Close()
        except BaseException:
            print "Close Exception!!"


    # 删除文档中恶意广告信息,只要包含制定字符,即删除整个textRange。
    # 此方法,主要针对"www.1ppt.com"。
    # 有删除操作返回true
    def RemoveTextRange(self, oKeyStr):
        oRet = False
        oSlideCounts = self.m_Doc.Slides.Count
        #遍历每一页,方便对每页数据进行操作
        for i in range(1 , oSlideCounts + 1):
            #print i ,"页"
            oSlide = self.m_Doc.Slides.Item(i)
            oShapeCounts = oSlide.Shapes.Count
            #print oShapeCounts
            #遍历单页中所有shape
            for j in range(1,oShapeCounts + 1):
                oShape = oSlide.Shapes.Item(j)
                #判断类型,找到文字
                if oShape.TextFrame.HasText == msoTrue:
                    oTR = oShape.TextFrame.TextRange
                    try:
                        #oTextLen = oTR.Length
                        sText = oTR.Text
                        #转换为小写
                        sText = sText.lower()
                        #print sText

                        # 查找关键字,确认删除制定信息。
                        # 该方法并不用于最后一页,因为最后一页为整页的广告信息
                        oPos = sText.find(oKeyStr)
                        if oPos > 0  and i != oSlideCounts :
                            print "remove textRange" , i ,"+" ,oSlideCounts
                            oRet = True
                            oShape.Delete()
                            break
                        
                        if oPos > 0  and i == oSlideCounts :
                            print "delete Slide"
                            oRet = True
                            oSlide.Delete()
                            break                       

                    except BaseException:
                        print "BaseException"
        return  oRet


def testDoc():
    oFilePath = r"D:\pptSpider\PPTFile1\A版小学五年级下册语文PPT课件\2015语文A版语文五下《一双新鞋》ppt课件.pptx"
    oKeyWork = "www.1ppt.com"
    print oFilePath
    oDoc = COfficeAdapter()
    if oDoc.OpenDoc(oFilePath):
        oRem = oDoc.RemoveTextRange(oKeyWork)
        #只有当删除页面元素时,才进行文档保存操作
        if oRem:
            oDoc.SaveDoc()
        oDoc.CloseDoc()

#testDoc()

接口分类比较清楚,具体内容就不讲了,需要注意两点:

  • 异常处理。解析上万文档,什么类型都会遇到,就拿OpenDoc来说,含密码、需修复和 打开失败等,异常情况很多,如果要想让代码不崩不断,tryCatch是免不了的。
  • MSO接口中,对象的删除是需要重建索引才能起作用的。在一套循环检索中, obj.delete()之后对象删了,但索引item还有。这个特点需要大家逐一。
关于多作业并行处理的优化方案

目前的实现逻辑是单作业串行操作,虽然文档处理速度是很快的,但由于文档量级较高,352个板块,3万份文档,一台PC机一天也没跑完。不过索性没断,就继续跑吧,等到数据分析的时候再做优化。

备注:

文档有了,脏数据也清干净了,下一步就是依据这些文档进行分析。抓的点我列了一半,周末再琢磨琢磨,下周就能开始跑了。
我争取尽快输出文档,和大家分享。同时,也欢迎各位提出自己的想法和意见。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容