2012-02-21 23 views
10

Tôi đã viết một tập lệnh bằng python sử dụng pywin32 để lưu tệp pdf vào văn bản cho đến khi gần đây hoạt động tốt. Tôi sử dụng các phương pháp tương tự trong Excel. Mã này là dưới đây:"Không được triển khai" Ngoại lệ khi sử dụng pywin32 để điều khiển Adobe Acrobat

def __pdf2Txt(self, pdf, fileformat="com.adobe.acrobat.accesstext"): 
    outputLoc = os.path.dirname(pdf) 
    outputLoc = os.path.join(outputLoc, os.path.splitext(os.path.basename(pdf))[0] + '.txt') 

    try: 
     win32com.client.gencache.EnsureModule('{E64169B3-3592-47d2-816E-602C5C13F328}', 0, 1, 1) 
     adobe = win32com.client.DispatchEx('AcroExch.App') 
     pdDoc = win32com.client.DispatchEx('AcroExch.PDDoc') 
     pdDoc.Open(pdf) 
     jObject = pdDoc.GetJSObject() 
     jObject.SaveAs(outputLoc, "com.adobe.acrobat.accesstext") 
    except: 
     traceback.print_exc() 
     return False 
    finally: 
     del jObject 
     pdDoc.Close() 
     del pdDoc 
     adobe.Exit() 
     del adobe 

Tuy nhiên mã này đã đột ngột ngừng làm việc và tôi nhận được kết quả như sau:

Traceback (most recent call last): 
    File "C:\Documents and Settings\ablishen\workspace\HooverKeyCreator\src\HooverKeyCreator.py", line 38, in __pdf2Txt 
    jObject.SaveAs(outputLoc, "com.adobe.acrobat.accesstext") 
    File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line 505, in __getattr__ 
    ret = self._oleobj_.Invoke(retEntry.dispid,0,invoke_type,1) 
com_error: (-2147467263, 'Not implemented', None, None) 
False 

Tôi có mã tương tự viết bằng VB mà làm việc một cách chính xác vì vậy tôi đoán rằng nó có gì để làm với các giao diện COM không ràng buộc với các chức năng thích hợp một cách chính xác? (kiến thức COM của tôi là rất nhiều).

+2

Liệu PDF này có lưu quyền sử dụng? (Dự đoán tự nhiên dựa trên tài liệu này: "Phương pháp này có sẵn trong Adobe Reader cho các tài liệu có quyền sử dụng Lưu.) –

+1

Có vẻ như tôi chưa kích hoạt chúng và vẫn gặp lỗi tương tự. Ngoài ra tôi đang sử dụng adobe acrobat để chạy mã: – Blish

Trả lời

3

blish, this thread nắm giữ chìa khóa dẫn đến các giải pháp bạn đang tìm kiếm: https://mail.python.org/pipermail/python-win32/2002-March/000260.html

Tôi thừa nhận rằng bài viết ở trên không phải là dễ dàng nhất để tìm thấy (có thể là vì Google đánh giá thấp dựa trên tuổi của nội dung?).

Cụ thể, áp dụng this piece lời khuyên sẽ có được những thứ chạy dành cho bạn: https://mail.python.org/pipermail/python-win32/2002-March/000265.html

Để tham khảo, các mảnh đầy đủ các mã mà không yêu cầu bạn phải tự có bản vá dynamic.py (đoạn nên chạy khá nhiều trong số các hộp):

# gets all files under ROOT_INPUT_PATH with FILE_EXTENSION and tries to extract text from them into ROOT_OUTPUT_PATH with same filename as the input file but with INPUT_FILE_EXTENSION replaced by OUTPUT_FILE_EXTENSION 
from win32com.client import Dispatch 
from win32com.client.dynamic import ERRORS_BAD_CONTEXT 

import winerror 

# try importing scandir and if found, use it as it's a few magnitudes of an order faster than stock os.walk 
try: 
    from scandir import walk 
except ImportError: 
    from os import walk 

import fnmatch 

import sys 
import os 

ROOT_INPUT_PATH = None 
ROOT_OUTPUT_PATH = None 
INPUT_FILE_EXTENSION = "*.pdf" 
OUTPUT_FILE_EXTENSION = ".txt" 

def acrobat_extract_text(f_path, f_path_out, f_basename, f_ext): 
    avDoc = Dispatch("AcroExch.AVDoc") # Connect to Adobe Acrobat 

    # Open the input file (as a pdf) 
    ret = avDoc.Open(f_path, f_path) 
    assert(ret) # FIXME: Documentation says "-1 if the file was opened successfully, 0 otherwise", but this is a bool in practise? 

    pdDoc = avDoc.GetPDDoc() 

    dst = os.path.join(f_path_out, ''.join((f_basename, f_ext))) 

    # Adobe documentation says "For that reason, you must rely on the documentation to know what functionality is available through the JSObject interface. For details, see the JavaScript for Acrobat API Reference" 
    jsObject = pdDoc.GetJSObject() 

    # Here you can save as many other types by using, for instance: "com.adobe.acrobat.xml" 
    jsObject.SaveAs(dst, "com.adobe.acrobat.accesstext") 

    pdDoc.Close() 
    avDoc.Close(True) # We want this to close Acrobat, as otherwise Acrobat is going to refuse processing any further files after a certain threshold of open files are reached (for example 50 PDFs) 
    del pdDoc 

if __name__ == "__main__": 
    assert(5 == len(sys.argv)), sys.argv # <script name>, <script_file_input_path>, <script_file_input_extension>, <script_file_output_path>, <script_file_output_extension> 

    #$ python get.txt.from.multiple.pdf.py 'C:\input' '*.pdf' 'C:\output' '.txt' 

    ROOT_INPUT_PATH = sys.argv[1] 
    INPUT_FILE_EXTENSION = sys.argv[2] 
    ROOT_OUTPUT_PATH = sys.argv[3] 
    OUTPUT_FILE_EXTENSION = sys.argv[4] 

    # tuples are of schema (path_to_file, filename) 
    matching_files = ((os.path.join(_root, filename), os.path.splitext(filename)[0]) for _root, _dirs, _files in walk(ROOT_INPUT_PATH) for filename in fnmatch.filter(_files, INPUT_FILE_EXTENSION)) 

    # patch ERRORS_BAD_CONTEXT as per https://mail.python.org/pipermail/python-win32/2002-March/000265.html 
    global ERRORS_BAD_CONTEXT 
    ERRORS_BAD_CONTEXT.append(winerror.E_NOTIMPL) 

    for filename_with_path, filename_without_extension in matching_files: 
     print "Processing '{}'".format(filename_without_extension) 
     acrobat_extract_text(filename_with_path, ROOT_OUTPUT_PATH, filename_without_extension, OUTPUT_FILE_EXTENSION) 

tôi đã thử nghiệm này trên WinPython x64 2.7.6.3, Acrobat X Pro

+1

Thêm winerror.E_NOTIMPL vào danh sách ERRORS_BAD_CONTEXT trong dynamic.py Đã làm việc Cảm ơn rất nhiều! – Blish

+1

Xin chào, tôi đang sử dụng trình đọc python và acrobat pro cho cùng một chức năng, và hiện tại mã này và thậm chí sau làm những gì mà người bình luận trước đã làm, đưa cho tôi lỗi sau: "NotAllowedError: Thiết lập bảo mật ngăn chặn truy cập vào thuộc tính hoặc phương thức này". Bạn có biết nguyên nhân gây ra nó không? Cảm ơn bạn – dasen

+2

Tôi không thể đưa bạn đủ cho 'ERRORS_BAD_CONTEXT.append (winerror.E_NOTIMPL) 'dòng. – Fenikso

1

makepy.py là tập lệnh đi kèm với gói python win32com.

Chạy nó để cài đặt "dây" python vào đối tượng COM/OLE trong Windows. Sau đây là một đoạn trích của một số mã tôi đã sử dụng để nói chuyện với Excel và làm một số công cụ trong đó. Ví dụ này lấy tên của trang tính 1 trong sổ làm việc hiện tại. Nó sẽ tự động chạy makepy nếu nó có một ngoại lệ:

import win32com; 
import win32com.client; 
from win32com.client import selecttlb; 

def attachExcelCOM(): 
    makepyExe = r'python C:\Python25\Lib\site-packages\win32com\client\makepy.py'; 
    typeList = selecttlb.EnumTlbs(); 
    for tl in typeList: 
     if (re.match('^Microsoft.*Excel.*', tl.desc, re.IGNORECASE)): 
      makepyCmd = "%s -d \"%s\"" % (makepyExe, tl.desc); 
      os.system(makepyCmd); 
     # end if 
    # end for 
# end def 

def getSheetName(sheetNum): 
    try: 
     xl = win32com.client.Dispatch("Excel.Application"); 
     wb = xl.Workbooks.Item(sheetNum); 
    except Exception, detail: 
     print 'There was a problem attaching to Excel, refreshing connect config...'; 
     print Exception, str(detail); 
     attachExcelCOM(); 
     try: 
     xl = win32com.client.Dispatch("Excel.Application"); 
     wb = xl.Workbooks.Item(sheetNum); 
     except: 
     print 'Could not attach to Excel...'; 
     sys.exit(-1); 
     # end try/except 
    # end try/except 

    wsName = wb.Name; 
    if (wsName == 'PERSONAL.XLS'): 
     return(None); 
    # end if 
    print 'The target worksheet is:'; 
    print '  ', wsName; 
    print 'Is this correct? [Y/N]',; 
    answer = string.strip(sys.stdin.readline()); 
    answer = answer.upper(); 
    if (answer != 'Y'): 
     print 'Sheet not identified correctly.'; 
     return(None); 
    # end if 
    return((wb, wsName)); 
# end def 

# -- Main -- 
sheetInfo = getSheetName(sheetNum); 
if (sheetInfo == None): 
    print 'Sheet not found'; 
    sys.exit(-1); 
else: 
    (wb, wsName) = sheetInfo; 
# end if 
Các vấn đề liên quan