젠스 알브레히트, 시다르트 라마찬드란, 크리스티안 윙클러, 『파이썬 라이브러리를 활용한 텍스트 분석 Blueprints for Text Analytics Using Python』, 심상진, 한빛미디어-OREILLY(2022), p69-96.
Learned
API
통신할 수 있도록 해주는 인터페이스
- 사용자가 소프트웨어 응용 프로그림애나 구성 요소, 서비스 등이 어떻게 구현되는지 몰라도 됨
- 사용할 수 있는 요청의 종류, 사용되는 데이터 형식, 예상 응답을 포함하는 일련의 정의 및 프로토콜을 제공
- 웹사이트 스크랩보다 선호되는 접근 방식
- 호출 가능한 함수로 설계됨
- 사용하기 쉽고 자동화할 수 있음
- 데이터가 자주 변경되거나 프로젝트에 최신 정보를 반영해야 할 때 권장
SOAP vs REST vs GraphQL
- SOAP (Simple Object Access Protocol)
- 표준 인터페이스를 사용해 서로 다른 소프트웨어 모듈이 통신하는 초기 방법의 하나
- XML을 사용해 캡슐화된 표준 메시징 형식을 사용
- 모든 통신 프로토콜 (ex. HTTP, TCP)을 사용해 메시지를 전송
- 일반적으로 오래된 프로토콜로 간주됨 (주로 대기업 레거스 응용 프로그램 내에서 사용됨)
- REST (Representational State Transfer)
- 통신 프로토콜로써 상태 코드를 사용해 호출의 성공 or 실패 정보를 표현하는 HTTP에 의존
- 데이터 유형을 훨씬 느슨하게 정의
- 보통 JSON을 사용
- 여러 웹 기반 서비스에서 채택하여 사용하는 형식
- 단일 정보를 검색하려면 다른 리소스를 여러 번 호출해야한다는 단점이 있음
- GraphQL
- 그래프 쿼리 언어
- SQL 쿼리 작성과 유사한 API와 상호 작용하는 방법을 정의하는 방식
- 단일 정보를 검색하는데 유용함 (w. SQL 쿼리)
Python - requests
headers 객체
- 서버명, 응답 타임스탬프, 상태 등 자세한 정보를 담고 있는 사전형 객체
상태 코드 (Status Code)
- 1xx (Informational): The request was received, continuing process
- 2xx (Successful): The request was successfully received, understood, and accepted
- 3xx (Redirection): Further action needs to be taken in order to complete the request
- 4xx (Client Error): The request contains bad syntax or cannot be fulfilled
- 5xx (Server Error): The server failed to fulfill an apparently valid request
검색 API 사용
- 매개변수 제공 (ref. API 설명서)
response = requests.get(
'https://api.github.com/search/repositories',
params={'q': 'data_science+language:python'}, # 매개변수
headers={'Accept': 'application/vnd.github.v3.text-match+json'}
) # header
print(response.status_code) # 200
- 페이지 매기기
- 응답 개수를 제한하기 위해 사용하는 기술로 많은 API가 사용
- 응답 객체의 links 필드에 다음(next) 페이지와 마지막(last) 페이지 URL 정보를 제공함
def get_all_pages(url, params=None, headers=None):
output_json = []
response = requests.get(url, params=params, headers=headers)
if response.status_code == 200:
output_json = response.json()
if 'next' in response.links:
next_url = response.links['next']['url']
if next_url is not None:
output_json += get_all_pages(next_url, params, headers)
return output_json
out = get_all_pages(
"https://api.github.com/repos/pytorch/pytorch/issues/comments",
params={
'since': '2020-07-01T10:00:01Z',
'sorted': 'created',
'direction': 'desc'
},
headers={'Accept': 'application/vnd.github.v3+json'}
)
df = pd.DataFrame(out)
- 속도 제한 (rate limit)
- API가 모든 사용자에게 서비스를 제공하면서 인프라에 대한 부하를 방지하기 위함
- Ex. Github (Maximum 60/1hour)
- IP 주소를 기반으로 요청 수를 판단
- X-Ratelimit-Limit: 1시간 당 요청 수
- X-Ratelimit-Remaining: 현재 속도 제한을 넘기지 않고 보낼 수 있는 요청 수
- X-RateLimit-Reset: 요청 수가 재설정되는 시간
- 속도 제한을 초과하는 요청을 수행하는 경우, API는 403 응답
- IP 주소를 기반으로 요청 수를 판단
response = requests.head('https://api.github.com/repos/pytorch/pytorch/issues/comments')
print('X-Ratelimit-Limit', response.headers['X-Ratelimit-Limit']) # 60 (1시간 당 요청 수)
print('X-Ratelimit-Remaining', response.headers['X-Ratelimit-Remaining']) # 12 (현재 속도 제한을 넘기지 않고 보낼 수 있는 요청 수)
# Converting UTC time to human-readable format
import datetime
print(
'Rate Limits reset at',
datetime.datetime.fromtimestamp(int(response.headers\['X-RateLimit-Reset'\])).strftime('%c')
) # Rate Limits reset at Tue Jan 24 17:28:19 2023
- 속도 제한 준수 code
from datetime import datetime
import time
def handle\_rate\_limits(response):
now = datetime.now()
reset\_time = datetime.fromtimestamp(
int(response.headers\['X-RateLimit-Reset'\]))
remaining\_requests = response.headers\['X-Ratelimit-Remaining'\]
remaining\_time = (reset\_time - now).total\_seconds()
intervals = remaining\_time / (1.0 + int(remaining\_requests))
print('Sleeping for', intervals)
time.sleep(intervals)
return True
- 재시도
- requests 라이브러리는 재시도를 구현하지 않음
- Retry를 활용해서 별도로 구현해야됨
- 지정된 실패 조건의 경우 API 호출을 다시 시도할 수 있음
- backoff_factor: 각 시도 사이의 시간 지연을 점차적으로 증가시키는 용도
- time_delay = {backoff_factor} * (2 ** ({총 재시도 횟수} - 1))
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
retry_strategy = Retry(
total=5, # 총 재시도 횟수
status_forcelist=[500, 503, 504], # 지정된 에러만 다시 시도
backoff_factor=1 # 각 시도 사이의 시간 지연을 증가시킴
)
retry_adapter = HTTPAdapter(max_retries=retry_strategy)
http = requests.Session()
http.mount("https://", retry_adapter)
http.mount("http://", retry_adapter)
response = http.get('https://api.github.com/search/repositories',
params={'q': 'data_science+language:python'})
Twitter Example
- 지난 7일 동안 게시된 최근 트윗의 샘플만 검색 가능
- 페이지 매기기 → Cursor 객체로 가능
- lang: 언어 설정
- tweet_mode=’extended’: 모든 트윗의 전체 텍스트를 검색
- count: 한 번의 호출로 최대 검색 트윗 수 (속도 제한 용)
- items: 총 추출할 트윗 수
search_term = 'cryptocurrency OR crypto -filter:retweets'
tweets = tweepy.Cursor(api.search,
q=search_term, # 검색할 단어
lang="en", # 언어 설정
tweet_mode='extended', # 모든 트윗의 전체 텍스트를 검색
count=30).items(12000) # count : 한 번의 호출로 최대 검색 트윗 수 제한, # items: 12,000개 트윗으로 제한
- 속도 제한 초과 여부 확인
- wait_on_rate_limit: 자동 대기 기능 활성화
- wait_on_rate_limit_notify: 대기 시간 알림
api = tweepy.API(auth,
wait_on_rate_limit=True,
wait_on_rate_limit_notify=True,
retry_count=5,
retry_delay=10)
- 트윗에서 암호화폐와 함께 사용되는 해시태그 -> 메르세데스(Left) vs 페라리 트윗(Right)
- 메르세데스: 참가한 레이스에 초점
- 페라리: 상품과 드라이버를 홍보
Reference
- API
- backoff_factor
반응형
'NLP' 카테고리의 다른 글
Chapter 6. 텍스트 분류 알고리즘 (0) | 2023.03.26 |
---|---|
Chapter 5. 특성 엔지니어링 및 구문 유사성 (0) | 2023.03.26 |
Chapter 4. 통계 및 머신러닝을 위한 텍스트 데이터 준비 (0) | 2023.03.26 |
Chapter 3. 웹사이트 스크래핑 및 데이터 추출 (0) | 2023.03.26 |
Chapter 1. 텍스트 데이터에서 찾는 통찰 (0) | 2023.03.26 |
댓글