일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- CNN 실습
- Convolution Neural Network
- kt에이블스쿨
- AI
- 데이터분석
- MaxPooling2D
- fashion mnist
- 데이터크롤링
- 딥러닝
- CNN
- OneHotEncoding
- 인공지능
- pandas
- 모델평가
- NewsWhale
- 뉴스웨일
- AWS 입문자를 위한 강의
- 머신러닝
- explained AI
- Pooling Layer
- 데이터
- 크롤링
- 데이터처리
- CIFAR-10
- plot_model
- learning_rate
- 키워드 기반 뉴스 조회
- bias
- Neural Network
- CRISP-DM
- Today
- Total
jjinyeok 성장일지
웹크롤링 # 1 동적 페이지 크롤링 - 2022/08/03~2022/08/05 본문
8월 강의 일정 중 가장 궁금하던 수업이었다. 나는 현재 크롤링이 메인 서비스 중 하나인 앱서비스 개발을 진행하고 있다. 웹크롤링이 정말 재밌다는 것을 알기 때문에 기대되었고 혹시 내가 다 아는 내용이면 어쩌지 걱정되었다. 그러나 수업을 듣고 내가 느꼈던 것은 내 웹크롤링 코드는 우아하지 않고 효율적이지 않다는 것이었다. 부끄러웠다. 어서 새로운 버전의 크롤링 서버를 만들어야겠다고 생각했다.
아직 부족한 내 크롤링 서버 ver.1... 에이블스쿨에서 배운 내용을 참고해 8월 중순 안으로 버전업 시키겠다.
https://github.com/jjinyeok/NewsWhaleCrawling
GitHub - jjinyeok/NewsWhaleCrawling: 뉴스 구독 서비스 어플리케이션 '뉴스웨일' Crawling 프로그램 - By Python
뉴스 구독 서비스 어플리케이션 '뉴스웨일' Crawling 프로그램 - By Python. Contribute to jjinyeok/NewsWhaleCrawling development by creating an account on GitHub.
github.com
많이 늦었지만 버전 2를 만들었다. (2022/10/10) Scrapy를 통해 87% 정도 속도 향상을 이루어냈다.
https://github.com/jjinyeok/NewsWhaleCrawlingVer2
GitHub - jjinyeok/NewsWhaleCrawlingVer2: Scrapy를 사용한 Crawling Server입니다.
Scrapy를 사용한 Crawling Server입니다. Contribute to jjinyeok/NewsWhaleCrawlingVer2 development by creating an account on GitHub.
github.com
이제부터 3일동안 배웠던 우아하고 빠른 크롤링에 대해 정리하겠다.
1. 크롤링(Crawling)이란?
여러 페이지의 특정 데이터를 수집하고 분류하는 작업을 말한다. 데이터를 수집하는 작업을 스크래이핑(Scraping)이라 하는데 여러 스크래이핑 작업을 합쳐 크롤링이라 한다. 사실 크롤링과 스크래이핑이라는 단어의 구분이 모호하여 실무에서는 거의 같은 의미로 쓴다고 한다.
2. 웹 크롤링 방법은?
웹페이지는 정적 웹페이지와 동적 웹페이지로 나눌 수 있다.
- 정적 페이지
- 페이지의 데이터가 변경될 때 URL이 변경되는 페이지를 말한다.
- Response로 html 형식의 데이터를 가져온다.
- ex) pagenation을 통해 페이지가 변경될 때 URL이 바뀌는 경우 - 동적 페이지
- 페이지의 데이터가 변경될 때 URL이 변경되지 않는 페이지를 말한다.
- Response로 json 형식의 데이터를 가져온다.
- ex) 더보기란을 클릭할 때 URL이 바뀌지 않는 경우
웹 크롤링 방법은 웹 페이지의 종류에 따라 다르다. 동적 페이지의 경우 주로 requests 패키지를 이용하여 response로 JSON 문자열을 받아 파싱하는 방법을 사용하고 그것이 불가능하다면 selenium을 사용해 크롤링을 한다. 정적 페이지의 경우 주로 requests 패키지를 이용하여 response로 HTML 문자열을 받아 파싱하는 방법을 사용한다. 속도는 request json > request html > selenium 순서대로 빠르다. 따라서 가능하면 request json 방법으로 크롤링하는 방법이 selenium 방법으로 크롤링하는 것보다 낫다.
3. 동적페이지(request json) 웹 크롤링 프로세스
- 웹 서비스 분석 : 크롬 개발자 도구를 통해 URL을 찾아냄
- request(url) -> response(json) : json(str) : URL을 통해 request를 보내고 json 형식의 문자열을 response 받음
- json(str) -> list, dict -> DataFrame : 문자열 형식의 json을 리스트나 딕셔너리 자료형으로 바꾸고 데이터프레임 자료형으로 재가공함
다음 과정을 코스피 지수 일별 시세 데이터를 크롤링하는 예시를 통해 한 번 더 정리하겠다.
1. 웹 서비스 분석
먼저 코스피 지수 일별 시세 데이터를 크롤링할 수 있는 웹 서비스를 분석한다. 네이버 증권 코스피 웹서비스(https://m.stock.naver.com/domestic/index/KOSPI)를 사용하겠다.
이 페이지의 최하단부에 코스피 일별 시세를 보여주는 영역이 있다. 더보기를 클릭해보자.
데이터가 추가되었지만 URL이 변경되지 않았다. 현재 웹 페이지는 동적 페이지라는 것을 알 수 있다. 그럼 크롬 개발자 도구의 네트워크를 통해 현재 웹 페이지가 어떤 URL에 request를 통해 어떤 json 형식의 데이터를 가져오는지 살펴본다.
더보기를 눌렀을 때 웹페이지는 새로운 데이터를 웹페이지에 추가하기 위해 https://m.stock.naver.com/api/index/KOSPI/price?pageSize=10&page=2 URL로 GET 요청을 보낸다. 또한 10개의 json 형식의 데이터를 response 받는다는 것을 알 수 있다. 따라서 우리는 이 URL이 몇번째 page의 pageSize만큼의 데이터를 요청한다는 것을 추측하며 웹 서비스를 분석할 수 있다.
2. request(url) -> response(json)
URL을 통해 request를 보내고 json 형식의 문자열을 response 받을 것이다. 가장 코스피 일별 데이터를 받아오는 코드는 다음과 같다.
import requests
pageSize = 10 # 10 사이즈 (10개의 데이터)
page = 1 # 1 페이지 (가장 최신의 페이지)
url = f'https://m.stock.naver.com/api/index/KOSPI/price?pageSize={pageSize}&page={page}'
response = requests.get(url)
print(response) # <Response [200]>
print(response.text[:100]) # [{"localTradedAt":"2022-08-05","closePrice":"2,490.80","compareToPreviousClosePrice":"17.69","compar
쿼리 파라미터의 pageSize와 page 변수를 조절하며 response 받을 데이터를 선택한다.
3. json(str) -> list, dict -> DataFrame
이렇게 response 받은 데이터는 문자열 형식의 json이다. 데이터프레임을 만들기 위해 리스트나 딕셔너리 자료형이 유리하기 때문에 문자열 형식의 json을 리스트나 딕셔너리 자료형으로 변환하고 그것을 다시 필요한 정보만 포함한 데이터프레임으로 재가공하는 과정이 필요하다. 코스피 일별 시세 데이터의 거래일과 종가에 대한 데이터프레임을 만드는 코드는 다음과 같다.
import pandas as pd
data = response.json() # response 받은데이터를 리스트, 딕셔너리 형식으로 변환
print(type(data)) # <class 'list'>
print(type(data[0])) # <class 'dict'>
print(data[0]) # {'localTradedAt': '2022-08-05', 'closePrice': '2,490.80', 'compareToPreviousClosePrice': '17.69', 'compareToPreviousPrice': {'code': '2', 'text': '상승', 'name': 'RISING'}, 'fluctuationsRatio': '0.72', 'openPrice': '2,481.43', 'highPrice': '2,497.58', 'lowPrice': '2,480.05'}
df = pd.DataFrame(data)
print(df)
# localTradedAt closePrice compareToPreviousClosePrice compareToPreviousPrice fluctuationsRatio openPrice highPrice lowPrice
# 0 2022-08-05 2,490.80 17.69 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.72 2,481.43 2,497.58 2,480.05
# 1 2022-08-04 2,473.11 11.66 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.47 2,478.44 2,478.95 2,465.32
# 2 2022-08-03 2,461.45 21.83 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.89 2,438.56 2,461.45 2,433.12
# 3 2022-08-02 2,439.62 -12.63 {'code': '5', 'text': '하락', 'name': 'FALLING'} -0.52 2,451.00 2,451.07 2,428.76
# 4 2022-08-01 2,452.25 0.75 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.03 2,444.05 2,461.40 2,437.13
# 5 2022-07-29 2,451.50 16.23 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.67 2,453.53 2,463.05 2,442.01
# 6 2022-07-28 2,435.27 19.74 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.82 2,437.57 2,443.43 2,429.07
# 7 2022-07-27 2,415.53 2.57 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.11 2,412.52 2,415.53 2,396.19
# 8 2022-07-26 2,412.96 9.27 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.39 2,397.27 2,415.39 2,395.17
# 9 2022-07-25 2,403.69 10.55 {'code': '2', 'text': '상승', 'name': 'RISING'} 0.44 2,385.65 2,412.47 2,385.65
df = pd.DataFrame(data)[['localTradedAt', 'closePrice']]
print(df)
# localTradedAt closePrice
# 0 2022-08-05 2,490.80
# 1 2022-08-04 2,473.11
# 2 2022-08-03 2,461.45
# 3 2022-08-02 2,439.62
# 4 2022-08-01 2,452.25
# 5 2022-07-29 2,451.50
# 6 2022-07-28 2,435.27
# 7 2022-07-27 2,415.53
# 8 2022-07-26 2,412.96
# 9 2022-07-25 2,403.69
이 과정을 pageSize와 page를 parameter로 하고 거래일과 종가에 대한 데이터프레임을 return하는 함수로 구현한 코드는 다음과 같다.
def stock_price_kospi(pageSize, page):
"""This function is crawling stock price from NAVER web page.
Params
------
pageSize: int: one page size
page: int: page number
code: str: KOSPI or KOSDAQ
Return
------
type: DataFrame: display date, price columns
"""
import requests, pandas
url = f'https://m.stock.naver.com/api/index/KOSPI/price?pageSize={pageSize}&page={page}'
response = requests.get(url)
data = response.json()
return pd.DataFrame(data)[['localTradedAt', 'closePrice']]
print(stock_price_kospi(10, 2))
# localTradedAt closePrice
# 0 2022-07-22 2,393.14
# 1 2022-07-21 2,409.16
# 2 2022-07-20 2,386.85
# 3 2022-07-19 2,370.97
# 4 2022-07-18 2,375.25
# 5 2022-07-15 2,330.98
# 6 2022-07-14 2,322.32
# 7 2022-07-13 2,328.61
# 8 2022-07-12 2,317.76
# 9 2022-07-11 2,340.27
4. 추가적으로 알아둬야 할 부분
앞선 방식으로 크롤링을 진행할 때 오류가 나는 경우가 있다. 이때 request 패킷의 header에 값을 추가함으로써 문제를 해결할 수 있다. header의 user-agent, referer, cookie에 문제가 해결될 때까지 값을 넣어 request를 보낸다. 다음 사이트를 통한 환율 데이터 크롤링 예제로 정리하도록 하겠다. 다음 금융의 환율 사이트 (https://finance.daum.net/exchanges)에서 request URL을 찾을 수 있었다.
import requests
response = requests.get('https://finance.daum.net/api/exchanges/summaries')
print(response)
# <Response [403]>
기존 과정으로 request 패킷을 보냈을때 403 Response가 왔다. 403 에러는 Forbidden 즉 서버가 요청을 거부한 것이다. 이런 경우 header의 user-agent, referer, cookie에 문제가 해결될 때까지 값을 넣어 request를 보내야 한다.
구글 개발자 콘솔에서 요청헤더의 값을 확인하여 요청헤더를 추가해 request를 보내 403 Response를 막고 데이터를 크롤링 할 수 있다. 이 과정의 코드는 다음과 같다.
import requests
import pandas as pd
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
'referer': 'https://finance.daum.net/exchanges',
}
response = requests.get('https://finance.daum.net/api/exchanges/summaries', headers=headers)
print(response)
# <Response [200]>
data = response.json()['data']
df = pd.DataFrame(data)[['date', 'symbolCode', 'currencyCode', 'basePrice']]
print(df.head())
# date symbolCode currencyCode basePrice
# 0 2022-08-06 07:53:46 FRX.KRWUSD USD 1304.00
# 1 2022-08-06 07:53:46 FRX.KRWJPY JPY 966.03
# 2 2022-08-06 07:53:45 FRX.KRWCNY CNY 192.68
# 3 2022-08-06 07:53:45 FRX.KRWEUR EUR 1327.86
# 4 2022-08-06 07:53:45 FRX.KRWGBP GBP 1574.25
'[KT AIVLE School]' 카테고리의 다른 글
웹크롤링 # 3 정적 페이지 크롤링 - 2022/08/03~2022/08/05 (0) | 2022.08.08 |
---|---|
웹크롤링 # 2 Open API - 2022/08/03~2022/08/05 (0) | 2022.08.08 |
Python 라이브러리 # 2 pandas - 2022/08/01~2022/08/02 (0) | 2022.08.05 |
Python 라이브러리 # 1 NumPy - 2022/08/01~2022/08/02 (0) | 2022.08.02 |
프로젝트 관리 도구(GIT) #2 - 2022/07/27 (0) | 2022.07.28 |