使用 python-pptx 检查图像在 powerpoint 中是否具有装饰性

Check if image is decorative in powerpoint using python-pptx

我工作的公司要求在 .pptx 文档中列出所有无法访问的 images/shapes(没有替代文本,也没有装饰性)。为了使该过程自动化,我正在编写一个脚本,用于提取指定 .pptx 中所有无法访问的 images/shapes 并编译一个列表。到目前为止,我已经设法让它打印出没有替代文本的名称、幻灯片编号和图像块。

不幸的是,在广泛搜索文档后,我发现 python-pptx 包不支持检查 image/shape 是否装饰的功能。

我过去没有将 XML 元素映射到对象,我想知道如何制作一个函数来读取 adec:decorative 元素中的 val 属性这个 .pptx 文件(见第 4 行)。

<p:cNvPr id="3" name="Picture 2">
    <a:extLst>
        <a:ext uri="{FF2B5EF4-FFF2-40B4-BE49-F238E27FC236}"><a16:creationId xmlns:a16="http://schemas.microsoft.com/office/drawing/2014/main" id="{77922398-FA3E-426B-895D-97239096AD1F}" /></a:ext>
        <a:ext uri="{C183D7F6-B498-43B3-948B-1728B52AA6E4}"><adec:decorative xmlns:adec="http://schemas.microsoft.com/office/drawing/2017/decorative" val="0" /></a:ext>
    </a:extLst>
</p:cNvPr>

由于我最近才开始使用这个包,所以我不确定如何在 python-pptx 中创建自定义元素 类。如果有人有任何其他解决方法或建议,请告诉我,谢谢!

创建一个自定义元素 class 当然可以,但我认为这是一种极端的方法(想想杀蚊子的火箭筒):)。

我倾向于认为您可以通过 XPath 查询您可以通过 python-pptx.

找到的最近的祖先来完成您想要的事情

这样的事情是正确的方向:

cNvPr = shape._element._nvXxPr.cNvPr
adec_decoratives = cNvPr.xpath(".//adec:decorative")
if adec_decoratives:
    print("got one, probably need to look more closely at them")

挑战之一可能是注册 adec 名称空间前缀,因为我认为它不是默认设置。所以您可能需要在 XPath 表达式之前执行此代码,可能在加载第一个文档之前:

from pptx.oxml.ns import _nsmap

_nsmap["adec"] = "http://schemas.microsoft.com/office/drawing/2017/decorative"]

此外,如果您稍微研究一下 XPath,我认为您实际上可以查询具有 val=0 或任何特定属性状态的 <adec:decorative> 元素满足您的需求.

但这是我推荐的方向。也许您可以 post 计算出结果后,以防其他人以后遇到同样的问题。

毕竟问题简单多了!也非常感谢@scanny,我能够解决问题并针对 adec:decorative 元素中的 val=1 属性。以下函数 returns 如果该形状 val=1 则为真。

def isDecorative(shape):
    cNvPr = shape._element._nvXxPr.cNvPr
    adec_decoratives = cNvPr.xpath(".//adec:decorative[@val='1']")
    if adec_decoratives:
        return True

这是到目前为止检查单个指定 .pptx 中可访问性的完整脚本(打印出图像名称和幻灯片 # 如果图像不是装饰性的并且没有 alt-text):

from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE_TYPE
from pptx.enum.shapes import PP_PLACEHOLDER
from pptx.oxml.ns import _nsmap

_nsmap["adec"] = "http://schemas.microsoft.com/office/drawing/2017/decorative"

filePath = input("Specify PPT file path > ")
print()

def validShape(shape):
    if shape.shape_type == MSO_SHAPE_TYPE.PICTURE:
        return True
    elif shape.shape_type == MSO_SHAPE_TYPE.PLACEHOLDER:
        if shape.placeholder_format.type == PP_PLACEHOLDER.OBJECT:
            return True
        else:
            return False
    else:
        return False

def isDecorative(shape):
    cNvPr = shape._element._nvXxPr.cNvPr
    adec_decoratives = cNvPr.xpath(".//adec:decorative[@val='1']")
    if adec_decoratives:
        return True

# Note: References custom @property added to shared.py and base.py
def hasAltText(shape):
    if shape.alt_text:
        return True

def checkAccessibility(prs):
    for slide in prs.slides:
        for shape in slide.shapes:
            if validShape(shape) and not isDecorative(shape) and not hasAltText(shape):
                yield shape
                slideNumber = prs.slides.index(slide) + 1
                print("Slide #: %d " % slideNumber + "\n");

for picture in checkAccessibility(Presentation(filePath)):
    print(picture.name);