Как сделать сложное извлечение pdf с регулярным выражением

У меня есть файл PDF, содержащий победителей лотерейных билетов, я хочу извлечь все выигрышные билеты в соответствии с их призами.

PDF-файл

я пробовал это:

import re
import pdfplumber

prize_re = re.compile(r"^\d[a-z]")
cons_prize_re = re.compile(r"^Cons")
ticket1_line_re = re.compile(r"^\d[)]")
ticket2_line_re = re.compile(r"^\d{4}")
ticket3_line_re = re.compile(r"[A-Z] \d{6}")

with pdfplumber.open("./test11.pdf") as pdf:
    for i in range(len(pdf.pages)):
        page_text = pdf.pages[i].extract_text()

        for line in page_text.split("\n"):
            if prize_re.match(line) or cons_prize_re.match(line) or ticket1_line_re.match(line) or ticket2_line_re.match(line) or ticket3_line_re.search(line):
                print(line)

и я понял это, я не знаю, как назначить каждый билет своему призу, также номер билетов на призы против минусов кажется немного странным, я не знаю почему (AN 867952AO 867952AP должен быть => AN 867952 AO 867952 AP.. .):

1st Prize Rs :7000000/- 1) AU 867952 (MANANTHAVADY)
Cons Prize-Rs :8000/- AN 867952AO 867952AP 867952 AR 867952AS 867952
AT 867952 AV 867952 AW 867952AX 867952AY 867952
AZ 867952
2nd Prize Rs :500000/- 1) AZ 499603 (ADOOR)
3rd Prize Rs :100000/- 1) AN 215264 (KOTTAYAM)
2) AO 852774 (PATTAMBI)
3) AP 953655 (KOTTAYAM)
4) AR 638904 (PAYYANUR)
5) AS 496774 (VAIKKOM)
6) AT 878990 (WAYANADU)
7) AU 703702 (PUNALUR)
8) AV 418446 (WAYANADU)
9) AW 994685 (KOZHIKKODE)
10) AX 317550 (PATTAMBI)
11) AY 854780 (CHITTUR)
12) AZ 899905 (KARUNAGAPALLY
...

вместо этого я хочу получить:

 [
    {
        "1st Prize Rs :7000000",
        "tickets": [
            "AU 867952"
        ]
     },
    {
        "Cons Prize-Rs :8000",
        "tickets": [
            "AN 867952",
            "AO 867952",
            "AP 867952",
            "AR 867952",
            ...
        ]
     },
     ...
 ]

как я могу этого добиться?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
49
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете сначала получить все полные части со всех страниц в группах захвата.

Затем вы можете после обработки 3-й группы захвата получить отдельные «билеты» и в цикле создать нужную структуру данных.

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

^(\w+ Prize[-\s]Rs\s*):(\d+)/-(?:\s*\d+\))?\s*(.*(?:\n(?!\w+ Prize\b).*)*)

Демонстрация регулярных выражений

Для последующей обработки вы можете использовать шаблон для форматов билетов, который соответствует либо 2 символам верхнего регистра, пробелу и 6 цифрам, либо 4 или более цифрам, за которыми следует граница пробела.

(?:[A-Z]{2} \d{6}(?!\d)|(?<!\S)\d{4,}(?!\S))

Демонстрация регулярных выражений

Пример кода с использованием pdf-файла из вопроса:

import re
import pdfplumber
import json

pattern = r"^(\w+ Prize[-\s]Rs\s*):(\d+)/-(?:\s*\d+\))?\s*(.*(?:\n(?!\w+ Prize\b).*)*)"

with pdfplumber.open("./test11.pdf") as pdf:
    all_text = ""

    for page in pdf.pages:
        all_text += '\n' + page.extract_text()

    matches = re.finditer(pattern, all_text, re.MULTILINE)

    coll = []
    for matchNum, match in enumerate(matches):
        dct = {}
        dct[match.group(1)] = match.group(2)
        dct["tickets"] = re.findall(r"(?:[A-Z]{2} \d{6}(?!\d)|(?<!\S)\d{4,}(?!\S))", match.group(3))
        coll.append(dct)

    print(json.dumps(coll, indent=4))

Выход

[
    {
        "1st Prize Rs ": "120000000",
        "tickets": [
            "XG 218582"
        ]
    },
    {
        "Cons Prize-Rs ": "500000",
        "tickets": [
            "XA 218582",
            "XB 218582",
            "XC 218582",
            "XD 218582",
            "XE 218582"
        ]
    },
    {
        "2nd Prize Rs ": "5000000",
        "tickets": [
            "XA 788417",
            "XB 161796",
            "XC 319503",
            "XD 713832",
            "XE 667708",
            "XG 137764"
        ]
    },
    ....

Другие вопросы по теме