How to combine more than one page in a single PDF file when there are conditions?

Viewed 48

I'm using regular expressions to extract students' IDs from one large PDF file and save the associated's student page in a separate (one) PDF file. I've used this program for quite some time, however, I'm facing this problem where sometimes two pages may be associated with one student's ID. So, I have to combine two pages in one PDF file.

I created two lists, one for page numbers and one for students' IDs. As you can see below in the std_ID list, two IDs (index 2 and 3) are repeated, which means that pages numbered 2 and 3 must be combined separately resulting in a total of 4 pdf files.

pagesNumber = [0, 1, 2, 3, 4] 
std_ID = ['331401142', '439233718', '440113239', '440113239', '440113245']

A snippet of the code I'm currently using would yield 4 pdf files where index 2's page is totally ignored resulting in 440113239.pdf will have only index 3's page. Can somebody help?

    def split(self, folder):
        # file_base_name = self.pdf.replace('pdf', '')
        output_folder_path = os.path.join(os.getcwd(), folder)
        for page, ID in zip(pagesNumber ,std_ID ):
            pdfWriter = PdfFileWriter()
            pdfWriter.addPage(reader.getPage(page))
            with open(os.path.join(output_folder_path, '{0}.pdf'.format(ID)), 'wb') as f:
                pdfWriter.write(f)
                f.close()

Full code:

from PyPDF2 import PdfFileReader, PdfFileWriter
from time import time
import re, os




class Extract_Lab:
    global folder_Path, std_ID , pageNumber
    folder_name = "Rayat_Data\RAYAT_FILES"
    folder_Path = os.path.join(os.getcwd(), folder_name)
    pageNumber = []
    std_ID = []
    
    
    
    def __init__(self, pattern, pdf):
        self.pattern = pattern
        self.pdf = pdf
      
        
    def run(self):
        file = open(fr"{folder_Path}\{self.pdf}.pdf", 'rb')
        global reader 
        reader = PdfFileReader(file)
        for page in range(reader.numPages):
            sevPage = reader.getPage(page)
            pdfData = str(sevPage.extractText())
            match = re.findall(self.pattern,pdfData)
            for m in match: 
                std_ID.append(m)
                pageNumber.append(page)
        return std_ID, pageNumber


    def split(self, folder):
        # file_base_name = self.pdf.replace('pdf', '')
        output_folder_path = os.path.join(os.getcwd(), folder)
        for page, ID in zip(pageNumber ,std_ID):
            pdfWriter = PdfFileWriter()
            pdfWriter.addPage(reader.getPage(page))
            with open(os.path.join(output_folder_path, '{0}.pdf'.format(ID)), 'wb') as f:
                pdfWriter.write(f)
                f.close()


def main():
    start = time()
  
                   
    itmatch = '((?!1750111)[1|2|3|4]\d{8})'
    file_pdf = "SS05"
    obj = Extract_Lab(itmatch, file_pdf)
    lab, page = obj.run()
    obj.split(r"Rayat_Data\Trainees_Tables")
        

    print(f'Time taken: {time() - start}')


if __name__ == '__main__':
    main()


1 Answers

Assumptions std_id == pagesNumber and std_id is sorted

If my assumptions are true you can implement a pointer and counter. Use the counter to find how many connective ID's are duplicates. Will need to use the pointer to access List data.

Example:

    pointer = 0
    length = len(pagesNumber) -1
    while pointer <= length:    
        
            # Last page/id has been hit save the last page
            if pointer == length:
               ## save last page 
               #using std_id[pointer],pagesNumber[pointer]
                break
            
            count = 1
            # while loop to count how many duplicate ID's are in a row
            while std_id[pointer] == std_id[pointer + 1]:
                count+=1
                pointer+=1
                
                # the final ID is a duplicate
                if pointer == length and std_id[pointer] == std_id[pointer + 1]:
                    count+=1 
                    break
                # last value is not a duplicate break while loop
                elif pointer == length:
                    break 
            
            #If count > 1 
                ## do PDF joining for number of pages in count working back
            ## else just process one page

            pointer+=1
Related