파이썬 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]>&nbsp;', 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
    

    처럼 바꾸고 싶다는 의미이신 것 같습니다.

    제가 성경은 잘 모르지만 책 제목이 <숫자> <단어> 또는 <단어> <숫자> 형식으로 되어 있는 것 같네요. 그럼 패턴은 다음과 같습니다.

    1. 앞에 숫자가있고, 단어가 나오면 -> 그대로 쓴다
    2. 앞에 단어가 있고, 뒤에 숫자가 있으면 -> 숫자를 버린다

    이를 축약하면 (앞에 숫자가 있을수도 있다) 문자가 있다 인데요.

    이를 반영하는 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)를 모두 포함하기 위해서 썼습니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 설명까지 완벽해서 이해가 너무 잘 되네요!! 감사합니다. 덕분에 일주일밖에 안됐지만 파이썬 공부가 더 재밌어집니다 ㅋㅋ 알 수 없는 사용자 2017.2.3 13:13

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)