Как извлечь извлечь конкретный текст из файла PDF - Python - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь извлечь этот текст:

 DLA LAND AND MARITIME
ACTIVE DEVICES DIVISION
PO BOX 3990
COLUMBUS OH 43218-3990
USA
 Name: Desmond Forshey Buyer Code:PMCMTA9 Tel: 614-692-6154 Fax:   614-692-6930
 Email: Desmond.Forshey@dla.mil

из этого pdf файла . Я смог извлечь некоторый текст между двумя ссылками, используя код ниже:

import PyPDF2


pdfFileObj = open('SPE7M518T446E.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)

print(pdfReader.numPages)

pageObj1 = pdfReader.getPage(0)
pagecontent = pageObj1.extractText()


def between(value, a, b):
    # Find and validate before-part.
    pos_a = value.find(a)
    if pos_a == -1: return ""
    # Find and validate after part.
    pos_b = value.rfind(b)
    if pos_b == -1: return ""
    # Return middle part.
    adjusted_pos_a = pos_a + len(a)
    if adjusted_pos_a >= pos_b: return ""
    return value[adjusted_pos_a:pos_b]

desired = between(pagecontent,"5. ","8. ")
print(desired)

Код выше выводит это:

20
REQUEST FOR QUOTATIONSTHIS RFQ           IS             IS NOT A SMALL BUSINESS SET-ASIDE 4. CERT.FOR NAT. DEF.      UNDER BDSA REG. 2      AND/OR DMS REG. 15. ISSUED BY7. DELIVERY   9. DESTINATION10. PLEASE FURNISH QUOTATIONS TO THE       ISSUING OFFICE IN BLOCK 5 ON OR  BEFORE CLOSE OF BUSINESS (Date)IMPORTANT: This is a request for information,  and quotations furnished are  not offers. If you are unable  to quote, please so indicate on this form and return it to the  address in Block 5.   This  request  does not commit the Government to pay any costs incurred  in  the preparation of the submission of this  quotation or to contract for supplies  or services. Supplies are of domestic origin unless otherwise indicated by quoter. Any representations and/or certifications attached to this Request for Quotations must be completed by  the quoter.11. SCHEDULE  (See Continuation Sheets)     12. DISCOUNT FOR PROMPT PAYMENTd. CALENDAR DAYSNUMBERPERCENTAGE  NOTE:   Additional   provisions   and   representations                    are             are not attached.13. NAME AND ADDRESS OF QUOTERa. NAME OF QUOTER16. SIGNERAUTHORIZED FOR LOCAL REPRODUCTION Previous edition not useableSTANDARD FORM 18       (REV. 6-95)     Prescribed by GSA-FAR (48 CFR) 53.215-1(a)    SPE7M5-18-T-446E1. REQUEST NO.2018 APR 302. DATE ISSUED00739229623. REQUISITION/PURCHASE REQUEST NO.DO-C9RATINGDLA LAND AND MARITIME 
ACTIVE DEVICES DIVISION 
PO BOX 3990 
COLUMBUS OH  43218-3990 
USA 
Name: Desmond Forshey Buyer Code:PMCMTA9 Tel: 614-692-6154 Fax: 614-692-6930 
Email: Desmond.Forshey@dla.mil175 DAYS ADO 6. DELIVER BY  (Date)8. TO: c. CITYd. STATE b. STREET ADDRESS a. NAME OF CONSIGNEEe. ZIP CODE a. 10 CALENDAR DAYS (%)b. 20 CALENDAR DAYS (%) c. 30 CALENDAR DAYS (%)15. Date of Quotationa. NAME (Type or Print)  
AREA CODEc. TITLE (Type or Print)d. CITY  c. COUNTY    b. STREET ADDRESSe. STATE f. ZIP CODESee  Schedule2018 MAY 10NUMBERFOB DESTINATIONOTHER  (See Schedule)CAGE          b. TELEPHONE PAGE     OF      PAGES1 
POC INFORMATION: 

WHEN TECHNICAL DATA IS PROVIDED IT MUST BE OBTAINED AT:https://pcf1x.bsm.dla.mil/cfolders. DISCREPANCIES FOUND IN TECHNICAL DATA SHOULD SUBMIT 
REQUEST TO THE DLA CUSTOMER SERVICE WEBSITE:https://www.pdmd.dla.mil/cs/ 

ALL OTHER QUESTIONS (SOLICITATION REQUIREMENTS, ITEM DESCRIPTION, AWARD CHOICE, ETC.), PLEASE CONTACT THE BUYER SHOWN ABOVE. 

QUESTIONS REGARDING OPERATION OF THE DLA-BSM INTERNET BID BOARD SYSTEM SHOULD BE E-MAILED TO: DibbsBSM@dla.mil 

FOR IMMEDIATE ASSISTANCE, PLEASE REFER TO THE FREQUENTLY ASKED QUESTIONS (FAQS) ON BSM DIBBS AT: 
https://www.dibbs.bsm.dla.mil/Refs/help/DIBBSHelp.htm  OR PHONE 1-855-DLA-0001 (1-855-352-0001). 


MASTER SOLICITATION 

THIS SOLICITATION INCORPORATES THE TERMS AND CONDITIONS SET FORTH IN THE DLA MASTER SOLICITATION FOR AUTOMATED SIMPLIFIED 
ACQUISITIONS REVISION 46 (FEBRURARY 7, 2018) WHICH CAN BE FOUND ON THE WEB AT: 
http://www.dla.mil/Portals/104/Documents/J7Acquisition/Master%20Solicitation%20Rev-46%20February-7-2018.pdf?ver=2018-02-08-063754-70 

This solicitation incorporates technical/quality requirements (‚R™ or ‚I™ number in section B). The full text is in the DLA Technical and Quality Master List of Requirements at: 
http://www.dla.mil/HQ/Acquisition/Offers/eprocurement.aspx The revisionof the TQ Master in effect on the award date controls.14. SIGNATURE OF PERSON AUTHORIZED TO SIGN QUOTATION 1                20
###################
ISSUED BY7. DELIVERY   9. DESTINATION10. PLEASE FURNISH QUOTATIONS TO THE       ISSUING OFFICE IN BLOCK 5 ON OR  BEFORE CLOSE OF BUSINESS (Date)IMPORTANT: This is a request for information,  and quotations furnished are  not offers. If you are unable  to quote, please so indicate on this form and return it to the  address in Block 5.   This  request  does not commit the Government to pay any costs incurred  in  the preparation of the submission of this  quotation or to contract for supplies  or services. Supplies are of domestic origin unless otherwise indicated by quoter. Any representations and/or certifications attached to this Request for Quotations must be completed by  the quoter.11. SCHEDULE  (See Continuation Sheets)     12. DISCOUNT FOR PROMPT PAYMENTd. CALENDAR DAYSNUMBERPERCENTAGE  NOTE:   Additional   provisions   and   representations                    are             are not attached.13. NAME AND ADDRESS OF QUOTERa. NAME OF QUOTER16. SIGNERAUTHORIZED FOR LOCAL REPRODUCTION Previous edition not useableSTANDARD FORM 18       (REV. 6-95)     Prescribed by GSA-FAR (48 CFR) 53.215-1(a)    SPE7M5-18-T-446E1. REQUEST NO.2018 APR 302. DATE ISSUED00739229623. REQUISITION/PURCHASE REQUEST NO.DO-C9RATINGDLA LAND AND MARITIME 
ACTIVE DEVICES DIVISION 
PO BOX 3990 
COLUMBUS OH  43218-3990 
USA 
Name: Desmond Forshey Buyer Code:PMCMTA9 Tel: 614-692-6154 Fax: 614-692-6930 
Email: Desmond.Forshey@dla.mil175 DAYS ADO 6. DELIVER BY  (Date)

Как извлечь приведенный ниже текст из файла PDF?

DLA LAND AND MARITIME
ACTIVE DEVICES DIVISION
PO BOX 3990
COLUMBUS OH 43218-3990
USA
Name: Desmond Forshey Buyer Code:PMCMTA9 Tel: 614-692-6154 Fax:   614-692-6930
Email: Desmond.Forshey@dla.mil

1 Ответ

0 голосов
/ 01 мая 2018

Эта программа для чтения PDF не дает больших возможностей для взаимодействия со структурой возвращаемых данных. Тем не менее, можно добавить новую функцию, которая возвращает каждый элемент как другой элемент в списке. Тогда вы, по крайней мере, сможете извлечь данные между двумя элементами. Подход по-прежнему не является надежным, поскольку вам все еще нужно определиться с возможными случаями прекращения:

import PyPDF2
import itertools


def extractTextList(self):
    text_list = []
    content = self["/Contents"].getObject()
    if not isinstance(content, ContentStream):
        content = ContentStream(content, self.pdf)

    for operands, operator in content.operations:
        if operator == b_("Tj"):
            _text = operands[0]
            if isinstance(_text, TextStringObject) and len(_text.strip()):
                text_list.append(_text.strip())
        elif operator == b_("T*"):
            pass
        elif operator == b_("'"):
            pass
            _text = operands[0]
            if isinstance(_text, TextStringObject) and len(operands[0]):
                text_list.append(operands[0])
        elif operator == b_('"'):
            _text = operands[2]
            if isinstance(_text, TextStringObject) and len(_text):
                text_list.append(_text)
        elif operator == b_("TJ"):
            for i in operands[0]:
                if isinstance(i, TextStringObject) and len(i):
                    text_list.append(i)
    return text_list


from PyPDF2.pdf import PageObject, u_, ContentStream, b_, TextStringObject
PageObject.extractTextList = extractTextList


def between(text_elements, drop_while, take_while):    
    return list(itertools.takewhile(take_while, itertools.dropwhile(drop_while, text_elements)))[1:]    


pdfFileObj = open('SPE7M518T446E.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)

page0 = pdfReader.getPage(0)
text_elements = page0.extractTextList()

lines = between(text_elements, lambda x: x != 'RATING', lambda x: 'DAYS' not in x)
print('\n'.join(lines))

Это даст вам нужные строки, которые затем будут объединены в один вывод следующим образом:

DLA LAND AND MARITIME
ACTIVE DEVICES DIVISION
PO BOX 3990
COLUMBUS OH  43218-3990
USA
Name: Desmond Forshey Buyer Code:PMCMTA9 Tel: 614-692-6154 Fax: 614-692-6930
Email: Desmond.Forshey@dla.mil

Поскольку новая функция extractTextList() возвращает список текстовых элементов, найденных на странице, я использую itertools.dropwhile() и itertools.takewhile() для обработки возвращенного списка.

Функция between() работает в два этапа: сначала она читает список строк по одной за раз и отбрасывает их до тех пор, пока не будет соответствовать этому первому тесту (который должен найти RATING). Затем он начинает возвращать элементы в функцию takewhile(). Это продолжает принимать элементы, пока не обнаружит слово DAYS в одном из элементов. list() используется для создания отфильтрованного списка. Затем я опускаю первый элемент (как это слово RATING).

По сути это итеративный способ создания фрагмента в списке.

Примечание: lambda - это просто еще один способ определения функции. В этом случае он принимает текстовый элемент с именем x и возвращает True, если это определенное значение, или для такта, если слово DAYS находится где-то внутри него. Две функции itertool вызывают эти лямбда-функции для каждого элемента в списке.

...