사진에 는 행번호가 있는데 작으면 크게 띄워놓고 보고 만약 마크다운 편집기가 있다면 맨마지막에 코드를 올려놓을테니 마크다운 편집기에서 코드블럭으로 만들면 똑같은 행번호가 만들어질것이다.
설명
- 설명은 첫 줄부터가 아니라 순서도에 따라 설명한다
- 행번호를 말해 명확히 설명한다.
- 인수와 변수의 변화를 설명한다.
- 항상 클래스 관련된 공부를 할때는 노트에 인수와 변수의 이 계속 변하기 때문에 값을 메모해가면서 공부하면 이해하기가 쉽다.
40번 행에서 시작한다.
41번행
com_code
변수에삼성전자
의 코드번호005930
을 할당한다.42번행
crawler = StockDataCrawler(com_code)
crawler
라는 변수에 클래스의com_code
변수를 인자로 넣어 클래스를 실행하고 결과를crawler
변수에 넣는다클래스가 실행되고 7번행
def __init__(self, com_code):
함수가 실행된다. 인자 com_code 에는 005930이 들어간다.8번행
self.com_code = com_code
: sele.com_code변수에 0059030을 넣는다9번행 10번행
self.url = "https://finance.naver.com/item/sise_day.nhn?code="
,self.ua = UserAgent()
: self.url에는"https://finance.naver.com/item/sise_day.nhn?code="
주소를 넣고self.ua
에는UserAgent
를 넣는다.더이상 함수 호출을 하지 않으므로 다시 43번행으로 간다.
43번행
result = crawler.getAllStockData()
:crawler
변수가 클래스 안에 있는getAllStockData()
호출해서 함수를 실행시고 결과는result
에 넣는다32번행
def getAllStockData(self):
함수가 실행된다. 이 함수가 최종적인 값을 불러오는 함수이고 이 함수안에서 나머지 함수들을 실행해서 데이터를 가져오고 데이터프레임으로 정리한다.33번행
last_page = self.getLastPage()
:getLastPage()
함수를 실행하고 결과값을 last_Page에 넣는다.18번행
def getLastPage(self):
함수가 실행된다.19번행
url = self.url + self.com_code
: 7번행def __init__(self, com_code):
함수를 실행해서 얻은 변수 self.url 과 self.com_code변수의 값을 더해url
의 변수에 넣는다 결국url
의 값은https://finance.naver.com/item/sise_day.nhn?code=005930
이 된다.20번
soup = self.crawler(url)
: 12번행def crawler(self, url):
함수를 실행시키고 이 함수의 인자로url
의 변수(https://finance.naver.com/item/sise_day.nhn?code=005930
)를 넣는다.12번행
def crawler(self, url):
함수가 실행된다.13번행
headers = {'user-agent': self.ua.ie}
- User-Agent: HTTP 요청 헤더의 일종으로, 클라이언트(웹 브라우저 또는 기타 클라이언트)가 서버에게 자신의 유형과 버전을 알리는 데 사용된다. 일부 웹 서버는 특정 User-Agent를 감지하여 그에 맞는 내용을 제공하거나, 알려진 봇이나 스크래퍼의 접근을 제한할 수도 있다.
- self.ua.ie:이 코드에서
self.ua.ie
는UserAgent
클래스의 인스턴스인self.ua
로부터 Internet Explorer의 User-Agent 문자열을 가져오는 부분이다.fake_useragent
라이브러리를 사용하면, 여러 브라우저의 일반적인 User-Agent 문자열을 쉽게 얻을 수 있다. 이를 통해 서버가 요청을 일반 웹 브라우저로 인식하게 하여 크롤링을 더 원활하게 수행할 수 있다.
14번행
response = requests.get(url, headers=headers)
Python의
requests
라이브러리를 사용하여 HTTP GET 요청을 보내고 응답을 받아오는 부분이다.requests.get
함수는 주어진 URL로 HTTP GET 요청을 보냅니다. GET 요청은 일반적으로 서버로부터 데이터를 검색하는 데 사용된다. 여기서는 매개변수로 url과 headers를 설정해줘야한다.매개변수 url은 처음에
def crawler(self, url):
에서 받은 주소https://finance.naver.com/item/sise_day.nhn?code=005930
다.실제 이주소로 접속하기 때문에 최종주소는https://finance.naver.com/item/sise_day.nhn?code=005930&page=1
주소가 된다.매개변수 headers에는
{'user-agent': self.ua.ie}
의 가짜 user-agert값이 들어간다. 그 값을response
변수에 넣는다
보통 이런형태로 사용한다.url = "https://example.com" headers = {'user-agent': 'Mozilla/5.0'} response = requests.get(url, headers=headers) if response.status_code == 200: print("Request was successful") else: print("Failed to retrieve the page")
15번행
soup = BeautifulSoup(response.content, "html.parser")
- BeautifulSoup이라는 라이브러리로 데이터를 추출하기 위한 코드다.
response.content
는requests.get
요청의 결과로 받은 응답객체(사이트의 html)에서 바이트 형식의 본문 내용을 가져온다. html 웹 페이지의 전체 내용이 이 부분에 포함이 된다."html.parser"
는 Python의 표준 라이브러리에 포함된 HTML 파서로, 추가 설치 없이 사용할 수 있다. 다른 파서로는lxml
이나html5lib
등이 있으며, 각 파서는 장단점이 있다. 장단점은 내용일 길어서 따로 구글링하기 바란다.
16번행
return soup
요청한 페이지의 전체 html 문서가 들어있는soup
변수를 반환한다. 이soup
변수를 이름이 같은 20번행의soup
변수로 다시 넣어준다.21번행 우리는 한페이지만 크롤링 하는것이 아니라 마지막 페이지까지 크롤링 할것이므로 마지막 페이지를 가져오는 코드를 만들어야한다. 페이지의 구조는
https://finance.naver.com/item/sise_day.nhn?code=005930&page=1
이런식이다. 이 주소를 가지고 마지막 페이지를 가져온다21번행
last_page = int(soup.select_one('td.pgRR').a['href'].split('=')[-1])
https://finance.naver.com/item/sise_day.nhn?code=005930&page=1
이주소의 html정보가 들어있는soup
변수에서select_one('td.pgRR')
로 td 태그의 클래스 pgRR을 찾고.a['href']
로 클래스 pgRR에서 a태그의 주소를 가져와서.split('=')
로=
으로 나누면https://finance.naver.com/item/sise_day.nhn?code
,005930&page
,681
세개가 나오는데[-1]
로681
을 가져와서last_page
변수에 넣는다.last_page
변수의 값은 지금은681
이다.- 이 코드를 짤때는 크롤링 하고자 하는 주소의 마지마가 페이지로 가서 클래스를 찾아 넣어준다.
- 몇일동안 해보니까 같은 웹사이트라도 페이지가 늘어나고 줄어듬에 따라 클래스가 바뀐다. 이 부분은
getAllstockData
함수안에 반복문을 while문으로 바꾸면getLasPage
함수를 사용하지 않고도 끝까지 가져올수 있다.
22번행
return last_page
:last_page
변수의 값은 지금은1
이다.def getLastPage(self)
함수가 끝났으므로 다시 34번행으로 간다.34번행
df=None
df변수를 None값으로 초기화한다.- 초기화 하는 이유는 나중에 DataFrame을 저장할 준비를 하기 위해서다.
35번행
for page in range(1, last_page + 1):
이제부터 데이터를 가져오기 시작한다. 1페이지 부터last_page(681)
까지 반복해서 자료를 가져온다.36번행
data = self.getData(page)
: 숫자 1부터 마지막 페이지까지 getData함수의 인자로 넣어서 데이터를 가져온다 다시 24번행 으로 넘어간다.25번행
url = f'{self.url}{self.com_code}&page={page}'
:- self.url의 값은 :
https://finance.naver.com/item/sise_day.nhn?code=
- self.com_code의 값은 : 005930
- page의 값은 : 1
- 결국
https://finance.naver.com/item/sise_day.nhn?code=005930&page=1
이라는 값이url
변수로 들어간다.
- self.url의 값은 :
26번행
headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/'}
26번줄에서는 웹사이트의 html파일을 가져오기 위해서 가짜 user-agent를 사용했고 여기서는 데이터를 가져오기위해 user-agent를 따로 사용했다. 이 부분은 크롤링 대상 웹 사이트의 특정 요구 사항과 관련이 있을수 있다.27번행
req = requests.get(url, headers=headers)
: url과 user-agent정보로reqests
라이브러리를 사용해 get요청을 하고 가져온정보를 req변수에 넣는다.28번행
df = pd.read_html(req.text, encoding="euc-kr")[0]
: 판다스 라이브러리의read_html
을 사용하면 테이블 구조의 데이터를 쉽게 데이터 프레임으로 가져올수 있다.encoding="euc-kr"
이부분은 가져오html파일의 header부분에서 확인할 수 있다.
29번행
df = df.dropna().reset_index(drop=True)
:df.dropna()
:dropna
메서드는 결측치를 포함하는 모든 행을 제거한다. 이 작업은 특정 행이 유효한 데이터를 포함하지 않는 경우 해당 행을 제거하려는 의도로 사용된다.reset_index(drop=True)
: 기존에 인덱스를 제거하고 새로운인덱스를 만든다. 이렇게 하지 않으면 기존인덱스가 새로운 열이 되어서 쓸데없는 column이 생긴다
30번행
return df
가져온 데이터 프레임을 반환한다. 1페이지를 데이터 프레임으로 만든것이고 이작업을 마지막 페이지까지 반복한다.37번행
df = pd.concat([df, data], ignore_index=True)
: Pandas의pd.concat
함수를 사용하여 두 DataFrame (df
와data
)을 수직 방향으로 연결한다.df
: 기존의 DataFrame이다.data
:getDate()
함수로 가져오 새로운 페이지를 data변수에 넣었었다. 기존의 df와 수직방향으로 합쳐준다.ignore_index=True
: 이 파라미터는 연결 후에 인덱스를 재설정하라는 지시다. 만약 한페이에는 인덱스 번호가 1부터 50까지 있다면 수직방향으로 연결됐을때 인덱스가 1부터 50까지 계속 반복이 될것이다. 이것을 지우고 수직으로 연결이 되면 51부터 100으로 바꾸라는 설정이다. 이 결과를 다시df
변수에 넣어서 기존의 데이터 프레임으로 만들어준다.
38번행
return df
마지막페이지까지 수직방향으로 연결된 데이터 프레임 df변수를 반환한다.다시 44번행으로 간다.44번행
print(result)
수직방향으로 연결된 데이터 프레임 df변수를result
변수에 넣었고 출력한다.
import requests
import pandas as pd
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
class StockDataCrawler:
def __init__(self, com_code):
self.com_code = com_code
self.url = "https://finance.naver.com/item/sise_day.nhn?code="
self.ua = UserAgent()
def crawler(self, url):
headers = {'user-agent': self.ua.ie}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.content, "html.parser")
return soup
def getLastPage(self):
url = self.url + self.com_code
soup = self.crawler(url)
last_page = int(soup.select_one('td.pgRR').a['href'].split('=')[-1])
return last_page
def getData(self, page):
url = f'{self.url}{self.com_code}&page={page}'
headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'}
req = requests.get(url, headers=headers)
df = pd.read_html(req.text, encoding="euc-kr")[0]
df = df.dropna().reset_index(drop=True)
return df
def getAllStockData(self):
last_page = self.getLastPage()
df = None
for page in range(1, last_page + 1):
data = self.getData(page)
df = pd.concat([df, data], ignore_index=True)
return df
if __name__ == "__main__":
com_code = '005930' # 삼성전자 다른 종목을 이용할 때 활용
crawler = StockDataCrawler(com_code)
result = crawler.getAllStockData()
print(result)