2015-08-22 23 views
6

Ich muss Kopf- und Fußzeilen in vielen docx-Dateien entfernen. Ich habe gerade versucht, Python-DOCX-Bibliothek zu verwenden, aber es unterstützt keine Kopf- und Fußzeile in DOCX-Dokument zu diesem Zeitpunkt (in Arbeit).Python - Entfernen Sie Kopf- und Fußzeile aus docx-Datei

Gibt es eine Möglichkeit, das in Python zu erreichen?

Wie ich verstehe, ist docx ein XML-basiertes Format, aber ich weiß nicht, wie man es benutzt.

p.s.i. haben eine Idee lxml oder BeautifulSoup verwenden xml zu analysieren und einige Teile zu ersetzen, aber es sieht schmutzig

UPD. Danke an Shawn, für einen guten Startpunkt. Ich habe einige Änderungen am Skript vorgenommen. Dies ist meine finale Version (sie ist nützlich für mich, da ich viele .docx Dateien bearbeiten muss. Ich benutze BeautifulSoup, weil Standart XML Parser keinen gültigen XML-Baum bekommen kann. Auch meine docx Dokumente haben keine Kopf- und Fußzeilen in xml. Sie stellten nur die Bilder der und Fußzeile Kopfzeile in einem oben auf der Seite. auch Sie für mehr Geschwindigkeit lxml statt Suppe.

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) 

So verwenden können, das ist es :) ich weiß, das Code ist nicht sauber, sorry dafür.

Antwort

3

Nun, ich habe nie darüber nachgedacht, aber ich gerade ein test.docx mit einem Header und einer Fußzeile. Sobald Sie das docx haben, können Sie unzip es die konstituierenden XML-Dateien abrufen. Für meinen einfachen Testfall dies ergab:

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

Öffnung der word/documents.xml gibt Ihnen den Hauptproblembereich. Sie können sehen, dass es Elemente mit Header und Footer gibt. In meinem einfachen Fall bekam ich:

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

und

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

Alle doc tatsächlich klein ist, so

<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"/>""" 

So wird XML Manipulation kein Problem sein würde, entweder in Funktion oder in Leistung für etwas diese Größe. Hier ist ein Code, der Ihr Dokument in Python bringen, als XML-Baum analysieren und als docx speichern soll. Ich muss jetzt gehen, also ist das nicht deine komplette Lösung, aber ich denke, dass dir das den Weg ebnen sollte. Wenn Sie immer noch Probleme haben, werde ich später zurückkehren und sehen, wo Sie damit sind.

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

Vielen Dank! Dieser Code hat nicht funktioniert, aber nach einigen Refactoring wurde ich es gemacht! Danke noch einmal! – drjackild

+1

@drackild, gut. Was musste korrigiert werden? poste es und lass uns alle teilen :) –

Verwandte Themen