ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SKN Family AI 15기 5월 4주차 회고(2)
    기록../SKN Family AI 15기 2025. 5. 23. 16:33

    ✍️5월 22일 학습 내용


    변수 다루기

    • 파이썬은 동적 타이핑을 통한 변수 재할당이 가능한 언어
    • 다른 값을 여러 변수에 한 번에 할당할 수 있음

    None 값

    • 비어있거나 거짓인 상태를 나타내는 것이 아닌, 명시적으로 값이 없다는 표시
    • return 문으로 명시적으로 값을 반환하지 않는 함수는 기본적으로 None을 반환한다.
    • 함수 인자의 기본값이 없거나 기본값을 설정하고 싶지 않을 때 None으로 명시할 수 있다.
    • 변수를 초기화시킬 때 할당할 값이 없다면 사용할 수 있다.

    매개변수와 인자

    • 매개변수는 함수 정의시 선언되는 것이고, 인자는 실제로 함수에 들어가는 그 값이다.
    • 매개변수는 다음과 같은 방식으로 기본값을 설정할 수 있다.
    def greet(name, location="서울"): 
    #location을 "서울"로 기본 값을 주었습니다.
    #만약 별 다른 인자가 주어지지 않는다면, 서울로 출력됩니다.
        """주어진 이름과 장소로 인사를 생성합니다."""
        print(f"안녕하세요, {name}님! 여기는 {location}입니다.")
        # 함수 내부에서는 name과 location을 일반 변수처럼 사용합니다.
    

    반복문 변수 제어

    • continue 문을 만나면 해당 부분을 넘기고 다음 코드를 진행한다.
    for i in range(2,10):
    		if i < 5 :
    				continue
    				#5보다 작은 숫자는 건너뛰고 다음 문장을 출력한다.
    		print(i)
    
    • pass 문을 만나면 아무 작업도 수행하지 않고 넘어간다.
    • break 문을 만나면 그 즉시 반복을 중단한다.

    while

    • 조건 기반의 반복문
    • 무한 반복을 유도할 수 있으니 사용에 유의할 것
    while 조건식:
        # 조건식이 True인 동안 반복 실행될 코드 블록 (루프 본문)
        실행문1
        실행문2
        # 중요: 루프 본문 내에서 언젠가는 조건식이 False가 되도록
        #      상태를 변경하는 코드가 일반적으로 필요합니다.
    # while 루프가 종료된 후 (조건식이 False가 되면) 실행될 코드
    

    튜플

    • 튜플은 여러 개의 데이터를 순서대로 묶어서 관리하는 데이터형으로, 소괄호로 묶어서 만듦.
    • 불변한다는 특성을 가지고 있음.
    • 함수에서 소괄호를 쓰는 이유 → 데이터가 변하지 않게 하기 위함

    • {} 로 묶어서 표시함. 딕셔너리와 비슷하지만 키와 값으로 묶이지 않고 데이터가 각각 독립적
    • 중복 데이터를 허용하지 않음
    • 순서를 보장하지 않음
    • 셋에 저장되는 요소는 반드시 불변 타입의 데이터여야 함
    • 주요 연산
      • 합집합 .union(*다른_셋들)/+
      • 차집합 .difference(*다른_셋들)/&
      • 교집합 .intersection(*다른_셋들) /- *교집합은 빼기 연산. 연산 순서가 중요함

    전역변수와 지역변수

    • 함수 바깥에서도 사용할 수 있는 변수를 전역변수, 함수 내에서만 사용하는 변수를 지역변수라고 함
    • 동일한 변수명이 있다면 함수 내에서는 지역 변수가, 그 외의 상황에서는 전역 변수가 우선시 됨 (지역변수는 다른 영역에서 인식되지 않음. 사라짐.)
    • 함수 내에서 전역 변수를 선언하고 싶다면, global 키워드를 사용할 수 있다.

    request모듈 사용하기

    • request 모듈은 인터넷에 접속하여 정보를 요청할 때 사용하는 모듈
    import requests #인터넷 접속을 위한 패키지지
    url = "<https://www.melon.com/song/detail.htm?songId=37139110>"
    
    head = {'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0'}
    
    r = requests.get(url, headers=head)
    r.text
    

    BeautifulSoup 모듈 사용하기

    • 텍스트 형태의 데이터를 HTML에 맞게 출력함.
    • 사용 예
    from bs4 import BeautifulSoup
    bs = BeautifulSoup(r.text)
    
    print(bs)
    
    • find() 메소드
    bs.find('div', class_="song_name")
    lyrics = BeautifulSoup(str(bs.find("div",id="d_video_summary")).replace("<br/>","\\n")).text
    lyrics.strip()
    

    OS 모듈 사용하기

    • 운영 체제 관련 기능들을 파이썬 코드 내에서 사용할 수 있도록 다양한 함수와 변수를 제공하는 핵심 표준 라이브러리
    • 아래 코드는 a.txt라는 파일을 쓰기모드로 열 수 있는 코드이다.
    if not os.path.isdir("./lyrics"):
        os.mkdir("./lyrics")
    f = open("./lyrics/a.txt", 'w', encoding='utf-8')
    

    응용 : 특정 링크의 노래 가사를 작성하기

    더보기
    import requests #인터넷 접속을 위한 패키지
    from bs4 import BeautifulSoup
    
    url = "<https://www.melon.com/song/detail.htm?songId=37139110>"
    
    head = {'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0'}
    
    r = requests.get(url, headers=head)
    print(r.text)
    
    bs = BeautifulSoup(r.text)
    print(bs)
    
    lyrics = BeautifulSoup(str(bs.find("div",id="d_video_summary")).replace("
    ","\\n")).text
    
    title = bs.find("div", class_="song_name").text.replace("곡명","").strip()
    artist = bs.find("div", class_="artist").text.strip()
    
    if not os.path.isdir("./lyrics"):
        os.mkdir("./lyrics")
    f = open(f"./lyrics/{artist}-{title}.txt", 'w', encoding='utf-8')
    
    f.write(lyrics.strip())
    f.close()
    
    

    ✍️5월 23일 학습 내용


    멜론에서 곡 이름을 검색하고, 해당 곡의 id를 통해 가사를 저장하는 코드

    가사를 저장하는 함수

    import requests 
    from bs4 import BeautifulSoup
    import os 
    
    def save_lyrics(songid, path='lyrics'):
    
        url = f"<https://www.melon.com/song/detail.htm?songId={songid}>"
        r = requests.get(url)
        head = {'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0'}
    
        r = requests.get(url, headers=head)
        bs = BeautifulSoup(r.text)
        lyrics = BeautifulSoup(str(bs.find("div", id="d_video_summary")).replace("
    ", "\\n")).text
    
        if not os.path.isdir(f"./lyrics/{path}") and path != 'lyrics':
            os.mkdir(f"./lyrics/{path}")
    
        title = bs.find("div", class_="song_name").text.replace("곡명", "").strip()
        artist = bs.find("div", class_="artist").text.strip()
        f = open(f"./lyrics/{path}/{artist}-{title}.txt", 'w', encoding='utf-8')
        f.write(lyrics.strip())
        f.close()
    
    • 해당 함수는 노래 가사 링크의 뒤에 들어오는 song_id를 매개변수로 받아 해당 곡의 가사를 추출하는 함수이다.
    from urllib.parse import urlparse, urlencode, quote
    
    def search_id(title):
        host = "<https://www.melon.com/search/total/index.htm?">
        payload = {
            'searchGnbYn' : ['Y'],
            'kkoSpl' :  ['Y'],
            'mwkLogType' : ['T']
        }
        payload['q'] = [title]
        #사용자가 넘겨준 제목을 검색어로 사용함
    
        url = host + urlencode(payload, doseq=True)
    
        return url
    
    
    • payload['q'] = [title]라는 코드는 사용자가 넘겨준 ‘제목’을 매개로 사용하여서 검색하겠다는 의미이다.
    • 이 함수를 사용하면, 해당 노래의 urlcode를 이용하여 host와 결합해 해당 노래의 가사가 있는 링크를 반환한다.
    url = search_id("너의 의미")
    
    #받은 url에 head 정보를 함께 넘겨주는 함수
    def my_request(url, method='get'):
            head = {
            'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0'
        }
            if method=='get':
                return requests.get(url, headers=head)
    
    r= my_request(url, 'get')
    bs = BeautifulSoup(r.text)
    bs.find("div", class_="tb_list d_song_list songTypeOne").find_all("tr")[1].find("button","btn_icon play" )
    
    • 결과

    💡

    <button class="btn_icon play" onclick="searchLog('web_tot','SONG_SONG','SO','너의 의미','4646573');melon.play.playSong('26020101',4646573);" title="재생" type="button"><span class="odd_span">재생</span></button>

     

    • 아래 코드는 정규 표현식을 통해 playSong 뒤로 이어지는 숫자를 추출하는 코드이다.
    • playSong('26020101',4646573) 부분에서 숫자 아이디를 추출하게 될 것이다.
    import re #정규표현식을 사용할 수 있는 파이썬 내장 모듈.
    p = re.compile("playSong\\(\\'([0-9]+)\\',([0-9]+)\\)")
    

    💡

    실행 결과

    '4646573’

    • 참고로 모든 숫자를 출력하도록 설정하면 리스트 안에 리스트 형태로 두 개의 숫자가 들어있다.
    • 아이디로 사용될 건 첫번째 리스트에서 마지막 숫자 문자열이므로, 해당 문자열을 사용하여 코드를 작성한다. </aside>
    • 위에 적은 내용들을 응용해서 하나의 모듈로 만들어보자
    from urllib.parse import urlparse, urlencode, quote
    import requests
    from bs4 import BeautifulSoup
    import re 
    
    def search_id(title):
        host = "<https://www.melon.com/search/total/index.htm?">
        payload = {
            'searchGnbYn' : ['Y'],
            'kkoSpl' :  ['Y'],
            'mwkLogType' : ['T']
        }
        payload['q'] = [title]
        #사용자가 넘겨준 제목을 검색어로 사용함
    
        url = host + urlencode(payload, doseq=True)
        #노래 제목을 키워드로 검색하여 url을 생성
        r = my_request(url, 'get')
        #header가 붙어 크롤링이 가능할 수 있도록 하는 코드 생성
        bs = BeautifulSoup(r.text)
        target = bs.find("div", class_="tb_list d_song_list songTypeOne").find_all("tr")[1].find("button","btn_icon play" )
        target = str(target)
        #크롤링 후 필요한 정보를 사용하기 위한 전처리
        
        p = re.compile("playSong\\(\\'([0-9]+)\\',([0-9]+)\\)")
        # 해당 페이지에서 숫자로 된 song id를 찾아온다.
        return p.findall(target)[0][-1]
    
    #받은 url에 head 정보를 함께 넘겨주는 함수
    def my_request(url, method='get'):
            head = {
            'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0'
        }
            if method=='get':
                return requests.get(url, headers=head)
    
    
    my_song = search_id("200%")
    print(my_song)
    #다양한 노래의 아이디를 얻을 수 있게 되었다!
    
    • 이제 song_id를 알고 있으니 song_id를 통해 가사 url을 찾아 가사를 저장할 수 있게 되었다.

    song_id를 통해 가사를 저장하기

    import requests 
    from bs4 import BeautifulSoup
    import os 
    
    def save_lyrics(songid, path='lyrics'):
    
        url = f"<https://www.melon.com/song/detail.htm?songId={songid}>"
        # songid를 사용해서 가사 url을 검색한다.
        r = my_request(url, 'get')
        bs = BeautifulSoup(r.text)
        lyrics = BeautifulSoup(str(bs.find("div", id="d_video_summary")).replace("
    ", "\\n")).text
    
        if not os.path.isdir(f"./lyrics/{path}") and path != 'lyrics':
            os.mkdir(f"./lyrics/{path}")
    
        title = bs.find("div", class_="song_name").text.replace("곡명", "").strip()
        artist = bs.find("div", class_="artist").text.strip()
        f = open(f"./lyrics/{path}/{artist}-{title}.txt", 'w', encoding='utf-8')
        f.write(lyrics.strip())
        f.close()
    

    가사가 잘 저장되었다 b

    응용 : 뉴스 기사의 링크를 입력하면, 그 뉴스의 제목을 이름으로 하고 내용을 저장하는 텍스트 파일을 만들어 저장하자.

    import requests 
    from bs4 import BeautifulSoup
    import os 
    import pathlib
    import re
    
    def news_save(link, path='news'):
        url = link
        # 입력한 기사를 통해 크롤링
        r = my_request(url, 'get')
        bs = BeautifulSoup(r.text)
        bs.find("span",class_= "end_photo_org").decompose
        #웹 크롤링에서 제일 중요한건 해당 객체의 속성과 이름입니다.
       
        text = BeautifulSoup(str(bs.find("div", id="newsct_article", class_="newsct_article _article_body")).replace("<br/>", "\\n")).text
        time = bs.find('div', class_='media_end_head_info_datestamp').find("span")['data-date-time'].replace(":","")
        if not os.path.isdir(f"./{path}") and path != 'news':
            os.mkdir(f"./{path}")
    
        title = bs.title.text.strip()
        safe_title = re.sub(r'[\\\\/:*?"<>|]', '', title)
        time = str(time)
    
        pathlib.Path(f"./{path}").mkdir(parents=True, exist_ok=True)
        f = open(f"./{path}/{safe_title}-{time}.txt", 'w', encoding='utf-8')
        f.write(text.strip())
        f.write(time.strip())
        f.close()
        
        return
    
    def my_request(url, method='get'):
            head = {
            'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0'
        }
            if method=='get':
                return requests.get(url, headers=head)
    
    

    파일을 읽어, 여성의 수와 남성의 수 구하기.

    • 이 코드는 다음 코드들을 응용하여 완성시킬 수 있습니다.
    import os
    os.listdir("./mydata")
    #해당 폴더에 들어있는 파일 목록들을 "리스트"형식으로 출력합니다.
    
    with open("./mydata/"+os.listdir("./mydata")[1], 'r') as f:
        print(f.read())
        
    #리스트화 한 파일의 내용을 읽어냅니다.
    
    sum(map(lambda x : int(x.replace(",","")),['1,000', '2,300', '3', '4']))
    # 리스트 내용을 맵핑한 후 모두 더할 수 있습니다.
    

    완성

    male =0
    female =0
    
    gender_list = os.listdir("./mydata")
    asset_list_f = []
    asset_list_m = []
    
    for i in range(len(gender_list)):
        if int(gender_list[i][-11]) % 2 ==0:
            female+=1
            
            with open("./mydata/"+os.listdir("./mydata")[i], 'r') as f:
                x = f.read()
                asset_list_f.append(x)
            
            
        else:
            male+=1
            
            with open("./mydata/"+os.listdir("./mydata")[i], 'r') as f:
                x = f.read()
                asset_list_m.append(x)
                
    man_total = sum(map(lambda x : int(x.replace(",","")),asset_list_m))
    man_avr = man_total // male
    woman_total = sum(map(lambda x : int(x.replace(",","")),asset_list_f))
    woman_avr = woman_total // female
    
    print(f"""리스트에서 여성은 = {female}명, 남성은 {male}명입니다.\\n
    여성의 평균은 {woman_avr: ,}이고, 남성의 평균운 {man_avr: ,}입니다.
          """)
          #위에 적은 f스트링은 천 단위로 자릿수를 끊어 표기하는 문법입니다. 참고하면 좋겠죠!!
    

     


    ✍️종합 회고

    KEEP:

    - 전공 지식이 어느 정도 도움이 되고 있고, 실습을 잘 따라가고 있다.

    - 실습 도중 남은 시간에는 실습으로 완성한 코드를 살짝 수정해서 응용하거나 출력을 다르게 해보며 프로그램을 익히고 있다.

     

    PROBLEM:

    - 가끔 환경 변수 문제인지 kernel이 잘 연결되지 않는 경우가 있다. 필요하면 환경을 재설정할 필요가 있을듯?

    - 강사님과 상호 작용을 잘 못한 것 같다!!

     

    TRY:

    - 세팅 환경 다음주에 다시 확인해보기

    - 좀 더 적극적으로 말하기

Designed by Tistory.