2015-08-22 31 views
6

Birçok docx dosyasında üstbilgileri ve altbilgileri kaldırmalıyım. Şu anda python-docx kütüphanesini kullanmaya çalışıyordum, ancak şu anda docx belgesinde üstbilgi ve altbilgiyi desteklemiyor (devam ediyor).Python - Üstbilgi ve altbilgiyi docx dosyasından kaldır

Python'da bunu başarmanın bir yolu var mı?

Anladığım kadarıyla, docx xml tabanlı bir biçimdir, ancak nasıl kullanılacağını bilmiyorum.

p.s.i'ye xml ayrıştırmak ve bazı parçaların değiştirilmesi için LXML veya BeautifulSoup kullanmak için bir fikrim var, ama o kirli

UPD'yi görünüyor. İyi bir başlangıç ​​noktası için Shawn'a teşekkürler. Senaryoda bazı değişiklikler yaptım. Bu benim son sürümü (benim için yararlıdır, çünkü birçok .docx dosyasını düzenlemem gerek. BeautifulSoup kullanıyorum çünkü standart xml ayrıştırıcı geçerli bir xml ağacı alamıyor. xml üstbilgi ve altbilgi. Onlar sadece sayfanın bir üst başlığının ve altbilginin yerleştirilen görüntüler. Ayrıca, daha çok hız için yerine çorbası lxml kullanabilirsiniz. Yani

import zipfile 
import shutil as su 
import os 
import tempfile 
from bs4 import BeautifulSoup 


def get_xml_from_docx(docx_filename): 
    """ 
     Return content of document.xml file inside docx document 
    """ 
    with zipfile.ZipFile(docx_filename) as zf: 
     xml_info = zf.read('word/document.xml') 
    return xml_info 


def write_and_close_docx(self, edited_xml, output_filename): 
    """ Create a temp directory, expand the original docx zip. 
     Write the modified xml to word/document.xml 
     Zip it up as the new docx 
    """ 
    tmp_dir = tempfile.mkdtemp() 

    with zipfile.ZipFile(self) as zf: 
     zf.extractall(tmp_dir) 

    with open(os.path.join(tmp_dir, 'word/document.xml'), 'w') as f: 
     f.write(str(edited_xml)) 

    # Get a list of all the files in the original docx zipfile 
    filenames = zf.namelist() 
    # Now, create the new zip file and add all the filex into the archive 
    zip_copy_filename = output_filename 
    docx = zipfile.ZipFile(zip_copy_filename, "w") 
    for filename in filenames: 
     docx.write(os.path.join(tmp_dir, filename), filename) 

    # Clean up the temp dir 
    su.rmtree(tmp_dir) 


if __name__ == '__main__': 
    directory = 'your_directory/' 
    files = os.listdir(directory) 
    for file in files: 
     if file.endswith('.docx'): 
      word_doc = directory + file 
      new_word_doc = 'edited/' + file.rstrip('.docx') + '-edited.docx' 
      tree = get_xml_from_docx(word_doc) 
      soup = BeautifulSoup(tree, 'xml') 
      shapes = soup.find_all('shape') 
      for shape in shapes: 
       if 'margin-left:0pt' in shape.get('style'): 
        shape.parent.decompose() 
      write_and_close_docx(word_doc, soup, new_word_doc) 

, işte bu :) biliyorum, Kod temiz değil, bunun için üzgünüm.

cevap

3

Eh, bunu hiç düşünmedim, ancak bir üstbilgi ve altbilgiye sahip bir test.docx oluşturdum. Bu docx'e sahip olduğunuzda, kurucu XML dosyalarını almak için unzip'u kullanabilirsiniz. Benim basit bir test durumu için, bu vermiştir: yukarı word/documents.xml

word/ 
_rels   footer1.xml  styles.xml 
document.xml  footnotes.xml  stylesWithEffects.xml 
endnotes.xml  header1.xml  theme 
fontTable.xml  settings.xml  webSettings.xml 

Açılış size asıl sorun alanını verir. Orada üstbilgi ve altbilgiye dahil olan elemanlar olduğunu görebilirsiniz. Benim basit durumda I got:

<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 wp14"> 
<w:body> 
    <w:p w:rsidR="009E6E8F" w:rsidRDefault="009E6E8F"/> 
    <w:p w:rsidR="00B53FFA" w:rsidRDefault="00B53FFA"/> 
    <w:p w:rsidR="00B53FFA" w:rsidRDefault="00B53FFA"/><w:p w:rsidR="00B53FFA" w:rsidRDefault="00B53FFA"> 
    <w:r> 
    <w:t>MY BODY</w:t> 
    </w:r> 
    <w:bookmarkStart w:id="0" w:name="_GoBack"/> 
    <w:bookmarkEnd w:id="0"/> 
    </w:p> 
    <w:sectPr w:rsidR="00B53FFA" w:rsidSect="009E6E8F"> 
    <w:headerReference w:type="default" r:id="rId7"/> 
    <w:footerReference w:type="default" r:id="rId8"/> 
    <w:pgSz w:w="12240" w:h="15840"/> 
    <w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="720" w:footer="720" w:gutter="0"/>""" 

Yani XML manipülasyon bir sorun olmayacak, bu nedenle

<w:headerReference w:type="default" r:id="rId7"/> 
<w:footerReference w:type="default" r:id="rId8"/> 

ve

<w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="720" w:footer="720" w:gutter="0"/> 

dokümanın tamamı aslında küçük, ya Bu boyutta bir şey için işlevde veya performansta. İşte, belgenizi python'a alması, xml ağacı olarak ayrıştırılması ve bir docx olarak geri kaydedilmesi gereken bir kod. Şimdi dışarı çıkmam gerekiyor, bu senin tam bir çözüm değil, ama bence bu seni yoldan çıkarmalı. Hala sorun yaşıyorsanız, daha sonra geri döneceğim ve onunla nerede olduğunuzu göreceğim.

import zipfile 
import shutil as su 
import os 
import tempfile 
import xml.etree.cElementTree 


def get_word_xml(docx_filename): 
    with open(docx_filename, mode='rt') as f: 
     zip = zipfile.ZipFile(f) 
     xml_content = zip.read('word/document.xml') 
    return xml_content 


def write_and_close_docx (self, xml_content, output_filename): 
     """ Create a temp directory, expand the original docx zip. 
      Write the modified xml to word/document.xml 
      Zip it up as the new docx 
     """ 

     tmp_dir = tempfile.mkdtemp() 

     self.zipfile.extractall(tmp_dir) 

     with open(os.path.join(tmp_dir,'word/document.xml'), 'w') as f: 
      xmlstr = tree.tostring(xml_content, pretty_print=True) 
      f.write(xmlstr) 

     # Get a list of all the files in the original docx zipfile 
     filenames = self.zipfile.namelist() 
     # Now, create the new zip file and add all the filex into the archive 
     zip_copy_filename = output_filename 
     with zipfile.ZipFile(zip_copy_filename, "w") as docx: 
      for filename in filenames: 
       docx.write(os.path.join(tmp_dir,filename), filename) 

     # Clean up the temp dir 
     su.rmtree(tmp_dir) 

def get_xml_tree(f): 
    return xml.etree.ElementTree.parse(f) 

word_doc = 'TEXT.docx' 
new_word_doc = 'SLIM.docx' 
doc = get_word_xml(word_doc) 
tree = get_xml_tree(doc) 
write_and_close_docx(word_doc, tree, new_word_doc) 
+0

Teşekkür ederiz! Bu kod işe yaramadı, ama bazı refactoring sonra ben yapıldı! Tekrar teşekkürler! – drjackild

+1

@drackild, iyi. düzeltilmesi gereken ne? yayınla ve paylaşalım :) –