【问题标题】:Extract text with lxml使用 lxml 提取文本
【发布时间】:2014-09-22 04:02:40
【问题描述】:

我有这段文字:

INTRODUCTION
This is a test document for xml.
I need to extract this sentence.

Conclusion
It should hopefully..

I need to extract this sentence. 行是斜体。该文件的 xml 如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n
<w:document 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
  mc:Ignorable="w14 w15 wp14">
   <w:body>
      <w:p w:rsidR="00470EEF" w:rsidRDefault="00456755">
         <w:pPr>
            <w:rPr>
               <w:b/>
            </w:rPr>
         </w:pPr>
         <w:r w:rsidRPr="00456755">
            <w:rPr>
               <w:b/>
            </w:rPr>
            <w:t>INTRODUCTION</w:t>
         </w:r>
      </w:p>
      <w:p w:rsidR="00456755" w:rsidRPr="00B042E3" w:rsidRDefault="00456755">
         <w:pPr>
            <w:rPr>
               <w:color w:val="FFFF00"/>
            </w:rPr>
         </w:pPr>
         <w:r w:rsidRPr="00B042E3">
            <w:rPr>
               <w:color w:val="FFFF00"/>
            </w:rPr>
            <w:t>This is a test document for xml.</w:t>
         </w:r>
      </w:p>
      <w:p w:rsidR="00456755" w:rsidRDefault="00E971E1">
         <w:r>
            <w:rPr>
               <w:i/>
            </w:rPr>
            <w:t>I need to extract this sentence.</w:t>
         </w:r>
         <w:bookmarkStart w:id="0" w:name="_GoBack"/>
         <w:bookmarkEnd w:id="0"/>
      </w:p>
      <w:p w:rsidR="00456755" w:rsidRDefault="00456755"/>
      <w:p w:rsidR="00456755" w:rsidRDefault="00456755">
         <w:pPr>
            <w:rPr>
               <w:b/>
            </w:rPr>
         </w:pPr>
         <w:r w:rsidRPr="00456755">
            <w:rPr>
               <w:b/>
            </w:rPr>
            <w:t>Conclusion</w:t>
         </w:r>
      </w:p>
      <w:p w:rsidR="00456755" w:rsidRPr="00456755" w:rsidRDefault="00456755">
         <w:r w:rsidRPr="00456755">
            <w:t>It should hopefully</w:t>
         </w:r>
         <w:r>
            <w:t>..</w:t>
         </w:r>
      </w:p>
      <w:sectPr w:rsidR="00456755" w:rsidRPr="00456755">
         <w:pgSz w:w="11906" w:h="16838"/>
         <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="708" w:footer="708" w:gutter="0"/>
         <w:cols w:space="708"/>
         <w:docGrid w:linePitch="360"/>
      </w:sectPr>
   </w:body>
</w:document>

我试过了:

tree = ET.parse(doc_xml)  
[b.tag for b in tree.iterfind(".//i")]  

上面返回一个空列表。

我已经搜索了很多,但无法弄清楚如何做到这一点,因为文本包含在 &lt;w:i/&gt; 中。我见过这个question,使用 BeautifulSoup 很容易做到这一点。

编辑:这并不完全相关,但这是提取所有文本的 ElementTree 方法。

w = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' 
    for p in source.findall('.//{' + w + '}p'):
        print ''.join(t.text for t in p.findall('.//{' + w + '}t'))

【问题讨论】:

  • 你可能需要告诉它使用URI为"http://schemas.openxmlformats.org/wordprocessingml/2006/main"的命名空间,方法是绑定一个前缀,比如w
  • 是的,我已经这样做了,甚至通过'p'标签和't'标签提取了所有文本..
  • 请告诉我们你做了什么。您展示的 Python 并未表明使用任何命名空间。
  • 我查看了 xpath 语法,发现这里没有“id”。那么我怎样才能归零到一个特定的标签呢?
  • @LarsH 在 lxml 中是否可能出现上述情况?路径并不总是固定的。遍历整个 xml 并返回与“i”相对应的文本

标签: python xml xpath lxml elementtree


【解决方案1】:

稍微修改一下你就会得到你想要的:

>>> w = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'    
>>> for t in tree.findall('.//{%(ns)s}i/../..//{%(ns)s}t' % {'ns': w}):
...     print t.text
... 
I need to extract this sentence.

顺便说一句,如果使用local-name(),则不需要指定命名空间(需要使用xpath方法,在lxml中可用):

>>> for t in tree.xpath('.//*[local-name()="i"]/../..//*[local-name()="t"]'):
...     print t.text
... 
I need to extract this sentence.

更新

.. 在表达式中选择当前节点的父节点。所以,{...}i/../.. 会选择i 节点的祖父节点。

【讨论】:

  • 谢谢它的工作!只是一个问题,xpath 看起来有点硬编码(也许我错了)。这会提取文本中任何子元素或元素下的“i”吗?
  • 太棒了,它按预期工作,遗憾的是我只能用我的个人资料投票一次:P
  • @Swordy,我不擅长文件格式;我的回答特定于您在问题中给出的 xml。如果您向我展示另一个格式不同的示例,我可以为您提供更通用的解决方案。
  • 不需要兄弟,我在几个不同结构的文档中对其进行了测试,效果很好。你介意添加代码解释吗?我很清楚它的作用.. 尤其是其中的 2 个 ../..//
  • @Swordy,哎呀,我错过了答案中最重要的部分。只是添加了解释。感谢您的反馈。
【解决方案2】:

根据您在编辑部分中的代码构建我的答案:

w = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main' 
for p in source.findall('.//{' + w + '}p[.//{' + w + '}i]'):
    print ''.join(t.text for t in p.findall('.//{' + w + '}t'))

基本上,第一个 XPath 应该匹配所有具有后代节点 &lt;w:i&gt;&lt;w:p&gt; 元素,然后您知道下一行从匹配的 &lt;w:p&gt; 节点中提取所有 &lt;w:t&gt; 节点的文本。

【讨论】:

  • 文件 "",行未知 SyntaxError: invalid predicate
  • 我猜 xpath 在这方面会做得更好。
  • 对不起,我没有找到你,你提到的文件&lt;string&gt;在哪里?上面代码中findall()方法的参数是XPath...
  • 我认为在第二行,你有p[//...],你的意思是p[.//...](根据你对它应该做什么的描述)。
  • @har07 是的,我的问题中的那个有效,但是您的代码给了我无效的谓词错误。正如我在第一条评论中提到的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-11
  • 1970-01-01
  • 1970-01-01
  • 2013-08-25
  • 2018-01-02
  • 1970-01-01
相关资源
最近更新 更多