Python парсер, использующий Regex для каталога курсов - PullRequest
1 голос
/ 27 мая 2020

Я пытался разработать тип синтаксического анализатора для старых каталогов курсов и имею представление о том, что я хочу сделать, но не могу понять этого. По сути, предпосылка состоит в том, что я хочу проанализировать и найти сокращения курсов, поэтому информатика будет сокращена как «(CS C)». Затем мне нужно будет найти номера курсов, название курса и единицы курса. Мой шаблон регулярного выражения для них прост:

course_abbrev = re.compile('\([A-Z]{3}\)')
course_num = re.compile('[0-9]{3},?')
course_title = re.compile('.+?(?=I )')
course_units = re.compile('\d')

Формат всех каталогов немного отличается, но они относительно следующие:

"""
Computer Science (CSC)  
Chairman: ...
201 Introduction to Computing I, 3
(Information of the course)...

220 Another Comp Class I, 3
(Information)... 
...  
...
...

Dental Hygiene (DHY)
Chairman: ...
101...
"""

Текст каталога несколько перемешан потому что он читается через PyPDF2, поскольку каталоги находятся в формате PDF, но поэтому я читаю страницу во время информации. Каким может быть эффективный метод поиска go сокращений, поиска номера после этого сокращения, чтобы затем найти заголовок после этого числа, а затем единицу курса. В модуле re есть способы перечислить все эти шаблоны (re.findall ()) или найти один из них (re.search ()), но я не уверен, как go найти один, сохранить его, а затем найти другой шаблон регулярного выражения оттуда, сохранение его и т. д. c.
РЕДАКТИРОВАТЬ: входные данные выглядят так благодаря PyPDF2, при этом страницы разбиваются и разделяются блоки информации:

COMPUTER SCIENCE (CSC) 
CHAIRMAN: Professor Name (Computer Science 
and Experimental Statistics) 
201 Introduction 
to Computing I and II, 3 
Algorithms, programs, and computers. Basic 
ming and program structure, data representation, 
zation and characteristics of computers. Computer 
tion of other stuff... 
(Lee. 3). Staff 220 Computers in Society 
II, 3 History, operation, application, and 
social significance of 
computers. Emphasis on the role of the computer in 
ciety with respect to more information and dan
gers. (Lee. 3) Carrano

1 Ответ

0 голосов
/ 30 мая 2020

Один из вариантов - использовать привязку \G для получения итеративных совпадений с использованием модуля регулярных выражений PyPi .

При циклическом цикле совпадений вы можете создать временный список, начиная с добавление первой группы только тогда, когда это не None

Затем добавьте к ней все остальные последующие группы и, наконец, добавьте временный список в список результатов.

(?:^.* \(([A-Z]{3})\).*|\G(?!^))(?:\r?\n(?!\d{3} |.* \([A-Z]{3}\)[^\S\r\n]*$).*)*\r?\n(\d{3}) (.*?) I, (\d+)

Пояснение

  • (?: Группа без захвата
    • ^.* \(([A-Z]{3})\).* Начало строки и захват в группе 1 трехкратного символа верхнего регистра AZ
    • | Или
    • \G(?!^) Подтвердить положительный результат в конце предыдущего совпадения, а не в начале
  • ) Закрыть группу
  • (?: Группа без захвата
    • \r?\n(?! Сопоставьте новую строку и подтвердите, что строка не содержит
    • \d{3} Сопоставьте 3 цифры и пробел
    • | OR
    • .* \([A-Z]{3}\)[^\S\r\n]*$).* Соответствие 3 заглавным буквам AZ в конце строки
  • )* Закрыть группу и r повторить это 0 или более раз
  • \r?\n Соответствует новой строке
  • (\d{3}) (.*?) I, (\d+) Соответствует 3 группам: 3 цифры перед заглавной I и 1+ цифр после I и запятая и пробел

Regex demo и Python demo

Пример кода

import regex

pattern = r"(?:^.* \(([A-Z]{3})\).*|\G(?!^))(?:\r?\n(?!\d{3} |.* \([A-Z]{3}\)[^\S\r\n]*$).*)*\r?\n(\d{3}) (.*?) I, (\d+)"

test_str = ("Computer Science (CSC)\n"
            "Chairman: ...\n"
            "201 Introduction to Computing I, 3\n"
            "(Information of the course)...\n\n"
            "220 Another Comp Class I, 3\n"
            "(Information)... \n"
            "...  \n"
            "...\n"
            "...\n\n"
            "Dental Hygiene (DHY)  \n"
            "Chairman: ...\n"
            "101 Introduction to Computing I, 3\n"
            "(Information of the course)...\n\n"
            "220 Another Comp Class I, 3\n"
            "(Information)... ")

matches = regex.finditer(pattern, test_str)
results = []
firstGroup = None

for matchNum, match in enumerate(matches, start=1):
    if match.group(1) is not None:
        firstGroup = match.group(1)

    tempList = [firstGroup]
    for groupNum in range(1, len(match.groups())):
        groupNum = groupNum + 1
        tempList.append(match.group(groupNum))
    results.append(tempList)
print(results)

Выход

[['CSC', '201', 'Introduction to Computing', '3'], ['CSC', '220', 'Another Comp Class', '3'], ['CSC', '101', 'Introduction to Computing', '3'], ['CSC', '220', 'Another Comp Class', '3']]
...