파이썬 regex 관련 질문!!
조회수 1162회
제가 각 책마다 chapter이 몇개씩 있는지를 알 수 있는 프로그램을 연습삼아 만들고 있는데, output이 제가 원하는대로 나오게 하기가 힘드네요. 아래에 title 변수와 관련된 질문입니다. 예를 들면 Ruth 만 제목으로 얻고싶은데 Ruth 1 이 나오거나, 코드를 바꾸어서 실행시켜서 Ruth가 나오게 하면 바로 그 다음 책인 1 Samuel에서 1만 output으로 얻게됩니다.
Ruth와 1 Samuel을 둘다 올바르게 얻을 수 없을까요?? 감사합니다.
import requests import re
def chapter_counter(max_book):
min_book = 1
while min_book <= max_book:
page = requests.get("http://www.holybible.or.kr/B_NIV/cgi/bibleftxt.php?VR=NIV&VL={}&CN=1&CV=99".format(min_book))
contents = str(page.content)
chapter = max(int(i) for i in re.findall(r'>(\d+)</[ab]> ', contents))
title = [str(s) for s in re.findall(r'height=12> <b>(\w+)(\s)(\w+)', contents)]
for w in title:
symbols = "~:!@#$%^&*()_+`{}|\"?><`-=\][';/.,']"
for i in range(0, len(symbols)):
w = w.replace(symbols[i], "")
print(w, 'has', chapter, 'chapters')
min_book += 1
chapter_counter(10)
-
(•́ ✖ •̀)
알 수 없는 사용자
1 답변
-
올려주신 코드를 실행하면
Genesis 1 has 50 chapters Exodus 1 has 40 chapters Leviticus 1 has 27 chapters Numbers 1 has 36 chapters Deuteronomy 1 has 34 chapters Joshua 1 has 24 chapters Judges 1 has 21 chapters Ruth 1 has 4 chapters 1 Samuel has 31 chapters 2 Samuel has 24 chapters
가 결과로 나오는데요. 이걸
... Ruth has 4 chapters 1 Samuel has 31 chapters 2 Samuel has 24 chapters
처럼 바꾸고 싶다는 의미이신 것 같습니다.
제가 성경은 잘 모르지만 책 제목이
<숫자> <단어>
또는<단어> <숫자>
형식으로 되어 있는 것 같네요. 그럼 패턴은 다음과 같습니다.- 앞에 숫자가있고, 단어가 나오면 -> 그대로 쓴다
- 앞에 단어가 있고, 뒤에 숫자가 있으면 -> 숫자를 버린다
이를 축약하면
(앞에 숫자가 있을수도 있다) 문자가 있다
인데요.이를 반영하는 regex는
(\d+\s)?[a-zA-Z]+
입니다. title과 w에 관련된 코드는 다음 한 줄로 줄일 수 있습니다.w = re.search(r'(?<=height=12>\s<b>)(\d+\s)?[a-zA-Z]+', contents).group()
(?<=height=12>\s<b>)(\d+\s)?[a-zA-Z]+
를 쪼개서 설명하면1.
(?<=height=12>\s<b>)
contents에서 찾고자 하는 부분이
<=height=12>\s<b>
로 시작하기 때문에 이 패턴이 필요합니다. 하지만 이 패턴은 추출하고자 하는 부분은 아니므로, positive look behind인(?<=...)
표현을 썼습니다.positive look behind는 이 패턴을 만족하는 스트링을 찾아야 하지만, 이 스트링을 결과에는 포함시키기 싫다 는 의미로 보시면 됩니다.
2.
(\d+\s)?
?
는 이 패턴이 있을 수도 있고, 없을 수도 있다 입니다. 처음 시작이 숫자인 경우(1 Samuel) 또는 아닌 경우 (Ruth 1)를 모두 포함하기 위해서 썼습니다.-
(•́ ✖ •̀)
알 수 없는 사용자
댓글 입력