인터프리터를 적극활용하자!
활용의 예)
In[1]: import os
In[2]: from bs4 import BeautifulSoup
In[3]: soup = BeautifulSoup(open('data/chart_realtime.html', 'rt').read(), 'lxml')
In[4]: tr = soup.find('tr', class_='lst50')
In[5]: tr
Out[5]: tr에 해당하는 soup객체 목록 표시
In[6]: tr.find('a', class_='song_info')
Out[6]: <a class="btn...>...</a>
원하는 정규표현식의 결과가 나왔는지, soup객체에 원하는 결과가 들어있는지 곧즉시 확인할 수 있는 좋은 방법
url = f'http://www.melon.com/
params = {
'song_id' : song_id,
}
song/detail.html'
response = requests.get(url, params)
soup = BeautifulSoup(response.text, 'lxml')
soup.find('div', class_='song_name').text
\n곡 명\n\t\t\t\t\t\\t\t\t\t\t\t\n\t\t\t\t\t\\t\t\t\Heart Shaker\n\t\t\t\t\t\t\t\
이런식으로 뜰때 해결방법
- div.song_name.contents[0]
- div.song_name.contents[1]
- div.song_name.contents[2]
- 엔터를 기준으로(?) song_name클래스에 내용을 보여줌
div.song_name.strong : strong클래스의 내용을 가져옴
div.song_name.strong.next_sibling : 해당 요소에 형제요소를 가져옴
div.song_name.strong.next_sibling.strip() : 공백문자 제거
get_text(strip=True) 받아온 텍스트의 양쪽 공백을 제거하는 메소드
ex) artest = div_entry.find(‘div’, class_=’artist’).get_text(strip=True)
Class 활용해서 melon Crawler작성하기
인스턴스의 첫번째 인자는 self이어야 한다.(인스턴스는 클래스 내의 함수?)
get/set 속성값과 프로퍼티
외부에서 접근할 수 없는 private 객체 속성을 지원함. 해당 속성을 읽기 위해서는 getter, setter메서드를 사용해야함.
그것을 파이썬에서는 property를 사용해 구현한다.
예를 들면 아래와 같은 클래스를 구현했다고 하면
class Song:
def __init__(self, title, album):
self.title = title
self.album = album
def show_info(self):
return f'{self.title|self.album}'
s1 = Song('좋니', 'LISTEN 010 좋니')
In: s1.title
In: s1.album
In: s1.show_info()
Out: '좋니'
Out: 'LISTEN 010 좋니'
Out: '좋니'|'LISTEN 010 좋니'
show_info()와 같이 굳이 표현하고 사용하는 것보다 이것을 속성처럼 접근하고 싶을 때 property를 사용한다.
class Song:
def __init__(self, title, album):
self.title = title
self.album = album
@property
def info(self):
return f'{self.title|self.album}'
def show_info(self):
return f'{self.title|self.album}'
s1 = Song('좋니', 'LISTEN 010 좋니')
다음과 같이 info라는 property를 추가하였다.
s1.info
를 입력하면
'좋니'|'LISTEN 010 좋니'
가 자동으로 출력된다.
property를 이용해서 s1객체의 속성으로 구현한 것이다.
property의 setter
property로 어떤 value를 만들었을 때 info(self)는 읽기가 되는데 이 setter는 프로퍼티에 어떤 값을 지정할 수 있다. info의 값은 우리가 init으로 받은 실제 값이 아니지만 setter를 이용하면 속성을 값을 대입할 수 있다(?).
아까 사용했던 예에 release_date를 추가해보자
class Song:
def __init__(self, title, album):
self.title = title
self.album = album
sef._release_date = release_date
@property
def info(self):
return f'{self.title|self.album}'
@property
def release_date(self)
return f'{self._release_date.strftim(%Y, %m, %d)}'
@release_date.setter
def release_date(self, new_date):
if not isinstance(new_date, datetime.datetime):
raise ValueError('datetime객체가 와야합니다')
elif new_date > datetime.datetime.now():
raise ValueError('지금보다는 과거여야 합니다')
self._release_date = new_date
def show_info(self):
return f'{self.title|self.album}'
s1 = Song('좋니', 'LISTEN 010 좋니')
` input: s1.release_date output: ‘2018.01.28’
release_date는 사실 속성이 아닌 그냥 접근하는 값인데(?) 값을 셋팅 가능하게 해주는 기능이 있다.
전부다 제대로 이해하지 못하고 쓰는 글이다보니 강사님이 말하는대로 그냥 써서 한국어지만 이해할 수없는 글이 되어버렸다..
내 나름대로 다시 정리를 하면, property는 우리가 정의한 클래스에 내장함수 처럼 속성을 만들어 주어 따로 불필요하게 메소드를 불러와 작동시키는 것을 효율적으로 활용할 수 있게 해주며 setter 메소드는 읽기 전용인 클래스 값에 접근할 수 있도록 하는 역할을 한다.
주말 숙제
숙제에서 구조를 어떻게 짜야되는지 잘 모르겠다는 분들이 많으셔서 알려드립니다!
예를들어 ‘아이유’로 검색하면 모든 항목이 존재하는데요 각 항목은 클래스명이 “section_atistinfo<숫자>"로 이루어져 있습니다숫자>
유명한 가수는 모든 섹션이 존재하지만, 아닐경우 한두개의 섹션밖에 없죠 저는 아이유와 검색하면 나오는 어떤 다른 중국가수를 비교하면서 만들었는데
섹션에 해당하는 요소가 있는지 검사해서 있을경우 추가, 없으면 빈값으로 놔두거나 빈값으로 할당하면됩니다
http://www.melon.com/artist/detail.htm?artistId=261143 http://www.melon.com/artist/detail.htm?artistId=167076
“아티스트 채널” 바로 밑에 있는 대표정보 (dict)와 수상이력(list) 아티스트 소개(str) 활동정보(dict) 신상정보(dict) 연관정보(dict)
를 저장하시면 됩니다
https://gist.github.com/LeeHanYeong/46ee8e98c963b7cebca6b137647497df
위의 gist에 실행코드, 결과 자료구조의 모습, 기본적인 속성값만 정의한 클래스를 올려드렸으니 궁금한점이 있으면 또 질문주세요!
Comments