【问题标题】:Python-docx and ElemetTree: how to find where hyperlinks lie within a paragraphPython-docx 和 ElemetTree:如何找到超链接在段落中的位置
【发布时间】:2020-05-01 17:34:43
【问题描述】:

我正在使用 python-docx 和 ElementTree 将 Word 文档转换为 XML,除了超链接之外,它运行良好。

我能够找到哪些 python-docx 段落具有超链接,但是如果超链接位于段落文本的中间,则在将输出写入 XML 时,我不知道在哪里呈现超链接。

有没有办法遍历段落中的所有元素? 如果我理解正确,遍历运行只会考虑 <w:r> 元素,所以我希望我的超链接元素将在 2 次运行之间。我怎么知道是哪两个?

【问题讨论】:

    标签: elementtree python-docx


    【解决方案1】:

    python-docx 使用lxml 处理其底层 XML。我希望如果你坚持这一点而不是引入 Python 的 xml.etree.ElementTree(如果这就是 ElementTree 的意思),你会做得更好。

    对于一个段落,你可以通过调用来生成底层的 XML 字符串:

    for paragraph in document.paragraphs:
        print(paragraph._p.xml)
    

    您还可以使用所有其他 lxml.etree._Element 方法,还有一个 python-docx 重载 .xpath() 方法,它允许您使用命名空间前缀而不是整个命名空间 URL 编写表达式,例如 paragraph._p.xpath("w:rPr")

    【讨论】:

    • 谢谢,我去看看lxml。
    • 你是说我不需要 ElementTree 类型的方法,但应该能够遍历段落并将paragraph._p.xml 直接写入输出文件?抱歉,我不是 SE,我确信我错过了完成这项任务的简单方法。
    • 您必须决定它是否足以满足您的应用程序,但无需进行 XML 操作级别的调用来检查 XML 文本中的段落。例如,您可以使用[p for p in document.paragraphs if "w:rPr" in p._p.xml] 对目标元素进行str 级别搜索。如果您确实需要直接操作 XML,我的意思是您应该使用 lxml 来完成,使用 python-docx 来获得 close 到您的元素需要和制作例如`paragraph._p.xpath("w:rPr") 从那里调用,而不是解压缩整个包并从顶部导航。
    • 非常感谢您的帮助。我不需要操作任何东西,只想直接将一个 docx 文件转换为 XML。开始这项工作的人认为 ElementTree 方法对于能够渲染图像和表格是必要的。
    【解决方案2】:

    我知道我来晚了,但也许有人会发现这个答案很有用。 假设您在 MS Word 文档中有一个段落,其中包含一个超链接,如下所示:

    一个由来已久的事实是,读者在查看页面布局时会被页面的可读内容分散注意力。 https://www.google.com/ 使用 Lorem Ipsum 的关键在于它具有或多或少的正态分布字母,而不是使用“这里的内容,这里的内容”,使它看起来像可读的英语。

    当您 1) 将 .docx 文件的扩展名更改为 .docx.zip 或 2) 通过打印 xml => print(paragraph._p.xml) 时,您可以检查它在 xml 中的样子 !)当您查看 document.xml 文件时,您会看到如下内容:

    <w:hyperlink w:history="1" r:id="rId9">
      <w:r w:rsidR="000D6596" w:rsidRPr="00302570">
       <w:rPr>
        <w:rStyle w:val="Hipercze"/>
        <w:rFonts w:cs="Arial"/>
        <w:spacing w:val="-4"/>
       </w:rPr>
      <w:t>https/google.com</w:t>
     </w:r>
    </w:hyperlink>
    

    然后您可以找到文档中所有超链接的关系 ID(如果您有多个超链接,您可能希望将 rIds 保存到列表中):

    import docx 
    from docx.oxml.ns import qn
    
    
    for paragraph in document.paragraphs:
            hyperlink = paragraph._p.xpath("./w:hyperlink")
            if len(hyperlink) > 0:
                hyperlink = hyperlink[0]
                hyperlink_rel_id = hyperlink.get(qn("r:id"))
    

    获得 rId 后,您可以访问该链接、删除、修改等。在此处获取 rId 的另一种方法:

            from docx.opc.constants import RELATIONSHIP_TYPE as RT
    
    
            link_text = 'https://www.google.pl/'
            document = docx.Document(path)
            rels = document.part.rels
            for rel in rels:
                if rels[rel].reltype == RT.HYPERLINK:
                    if rels[rel]._target == link_text:
                      # if the text of the link is the same as the one you are looking for 
                      # do something
    

    【讨论】:

      猜你喜欢
      • 2016-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-29
      • 1970-01-01
      • 2013-05-15
      相关资源
      最近更新 更多