2015-08-22 25 views
6

Tôi cần phải loại bỏ đầu trang và chân trang trong nhiều tệp docx. Tôi hiện đang thử sử dụng thư viện python-docx, nhưng nó không hỗ trợ đầu trang và chân trang trong tài liệu docx tại thời điểm này (công việc đang tiến hành).Python - Xóa đầu trang và chân trang khỏi tệp docx

Có cách nào để đạt được điều đó trong Python không?

Theo tôi hiểu, docx là định dạng dựa trên xml, nhưng tôi không biết cách sử dụng nó.

P.S.I có một ý tưởng để sử dụng lxml hoặc BeautifulSoup để phân tích xml và thay thế một số bộ phận, nhưng có vẻ bẩn

UPD. Nhờ Shawn, cho một điểm khởi đầu tốt. Tôi đã thực hiện một số thay đổi đối với tập lệnh. Đây là phiên bản cuối cùng của tôi (nó có ích cho tôi, vì tôi cần phải chỉnh sửa nhiều tệp .docx. Tôi đang sử dụng BeautifulSoup, vì trình phân tích cú pháp xml standart không thể nhận được xml-tree hợp lệ. Ngoài ra, tài liệu docx của tôi không có header và footer trong xml. Họ chỉ đặt hình ảnh của header và footer trong một đầu trang. Ngoài ra, cho tốc độ hơn, bạn có thể sử dụng lxml thay vì Soup.

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) 

vì vậy, đó là nó :) tôi biết, mã không sạch sẽ, xin lỗi vì điều đó.

Trả lời

3

Vâng, tôi chưa bao giờ nghĩ về nó, nhưng tôi vừa tạo một test.docx với đầu trang và chân trang. Khi bạn có docx đó, bạn có thể unzip nó để lấy các tệp XML thành phần. Đối với trường hợp thử nghiệm đơn giản của tôi, điều này mang lại:

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

Mở ra word/documents.xml cung cấp cho bạn vùng vấn đề chính. Bạn có thể thấy rằng có các yếu tố trong đó với đầu trang và chân trang có liên quan. Trong trường hợp đơn giản của tôi tôi nhận:

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

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

Tất cả các doc thực sự là nhỏ, vì vậy

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

Vì vậy, thao tác XML sẽ không là một vấn đề, một trong hai trong chức năng hoặc trong hiệu suất cho một cái gì đó kích thước này. Dưới đây là một số mã sẽ đưa tài liệu của bạn vào python, được phân tích cú pháp dưới dạng cây xml và được lưu lại dưới dạng docx. Tôi phải đi ra ngoài vì vậy đây không phải là giải pháp hoàn chỉnh của bạn, nhưng tôi nghĩ rằng điều này sẽ giúp bạn có được tốt xuống con đường. Nếu bạn vẫn gặp sự cố, tôi sẽ quay lại sau và xem bạn đang ở đâu với nó.

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

Cảm ơn bạn! Mã này đã không hoạt động, nhưng sau khi một số refactoring tôi đã được thực hiện nó! Cảm ơn một lần nữa! – drjackild

+1

@drackild, tốt. những gì cần phải được sửa chữa? đăng nó và chia sẻ tất cả :) –

Các vấn đề liên quan