python - 使用正则表达式作为课程目录的 Python 解析器
问题描述
我一直在尝试为旧课程目录开发一种解析器,并且知道我想做什么但无法弄清楚。基本上,前提是我要解析并找到课程缩写,所以Computer Science会缩写为“(CSC)”。接下来,我需要找到课程编号、课程名称和课程单元。我的正则表达式模式很简单:
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 格式,但因此我是在阅读信息时读取一页。一种有效的方法是查找缩写,查找该缩写后面的数字,然后找到该数字后面的标题,然后是课程单元。re 模块有办法列出所有这些模式 (re.findall()) 或搜索其中一个 (re.search()) 但我不确定如何找到一个、存储它,然后找到不同的来自那里的正则表达式模式,存储它等等。
编辑:由于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
解决方案
一种选择是利用锚点通过PyPi 正则表达式模块\G
获得迭代匹配。
在循环匹配时,您可以创建一个临时列表,仅当它不是 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 位数字和空格|
或者.* \([A-Z]{3}\)[^\S\r\n]*$).*
匹配字符串末尾的 3 个大写字符 AZ
)*
关闭组并重复 0 次或更多次\r?\n
匹配换行符(\d{3}) (.*?) I, (\d+)
匹配 3 组:大写前 3 个数字,theI
后 1+ 个数字,I
逗号和空格
示例代码
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']]
推荐阅读
- python - 未从自制模块定义的名称
- javascript - 在父级上打开 Vue 对话框(模态)
- python - 将自定义函数应用于 Pandas 数据框中的多列并在一列中返回输出
- java - the read function in java
- javascript - 如何在 React-Kotlin 中导入节点模块?
- android - 在 Android 设备上捕获未处理/原始麦克风数据
- python - 如何获取 Python 3.x 中录制的音频的频率和幅度?
- c# - 将一个 Web 部件嵌套在另一个 Web 部件中
- fortran - Fortran:将硬编码值传递给接受 real(16) 的函数不起作用。我怎样才能解决这个问题?
- asp.net - 将 Angular (6) 客户端错误发送到 Web API 以进行日志记录