본문 바로가기
AI데이터 엔지니어, 새싹

75th_12_20(Wed)_API활용 웹 크롤링

by Leetora 2024. 1. 8.
 
  • 과제 풀이

▶ 홈페이지 접속

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

# 네이버 접속
driver = webdriver.Chrome()
driver.get('https://some.co.kr/observatory/brand/57ac5b35-3900-44a1-8eea-3f0192f3c287')
driver.maximize_window()

▶ 전체 월 개수 계산

# 월 버튼 클릭
month_button = driver.find_element(By.CSS_SELECTOR, '#wrap > section > div > article > div.select-boxes.aos-init.aos-animate > div:nth-child(2) > div')
month_button.click()
# 전체 버튼 개수
total_month_count = len(month_button.find_elements(By.CSS_SELECTOR, 'li.option'))
 

▶ 페이지 이동

# 페이지 이동하는 함수 구현
import time

def move_month(month):
    month_button = driver.find_element(By.CSS_SELECTOR, '#wrap > section > div > article > div.select-boxes.aos-init.aos-animate > div:nth-child(2) > div')
    month_button.click()
    time.sleep(3)
    select_month = driver.find_element(By.CSS_SELECTOR, f"[data-value='{month}']")
    select_month.click()
    time.sleep(3)

▶ 특정 페이지에서 데이터 가져오기

# 값가져오기 함수 구현
import pandas as pd
def page_get_data():
    brand_list = driver.find_elements(By.CLASS_NAME, 'brand-ranking-card')
    result = []
    for i in brand_list:
        result.append(i.text.split('\n'))
    df = pd.DataFrame(result, columns = ['Week', 'Brand', 'Keyword'])
    return df

▶ 각 페이지별 데이터 저장

# 반복
result_df = pd.DataFrame()
month_button.click()
for month in range(1, total_month_count+1):
    move_month(month) 
    time.sleep(2)
    df = page_get_data()
    result_df = pd.concat([result_df, df])
result_df = result_df.reset_index(drop = True)
result_df

▶ 내가 작성한 코드

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

driver = webdriver.Chrome()
driver.get('https://some.co.kr/observatory/brand/57ac5b35-3900-44a1-8eea-3f0192f3c287')
driver.maximize_window()
time.sleep(2)

month_box = driver.find_element(By.CSS_SELECTOR, '#subject-swiper')
select_box = month_box.find_elements(By.CSS_SELECTOR, 'div.swiper-slide')
info = [i.text for i in select_box]
info_result = [i.split() for i in info]
week_list = [i[2] for i in info_result]
week_list
time.sleep(2)

result, month_list = [], []
for i in range(1, 13):
    # '월' 클릭
    month_bar = driver.find_element(By.CSS_SELECTOR, '#wrap > section > div > article > div.select-boxes.aos-init.aos-animate > div:nth-child(2)')
    month_bar.click()
    time.sleep(1)
    
    # '해당 월' 클릭
    select_month = driver.find_element(By.CSS_SELECTOR, f'#wrap > section > div > article > div.select-boxes.aos-init.aos-animate > div:nth-child(2) > div > ul > li:nth-child({i})')
    select_month.click()
    time.sleep(1)

    # index가 될 월을 리스트로 만들기
    month_box = driver.find_element(By.CSS_SELECTOR, '#subject-swiper > div:nth-child(1) > a > dl > dt').text
    month = month_box.split()
    month_list.append(month[1])
    
    # 주차별 정보 가져오기
    # 1. 주차별 브랜드가 적혀 있는 영역 선택하기
    brands = driver.find_element(By.CSS_SELECTOR, '#subject-swiper')
    time.sleep(1)
    
    # 2. 주차별 영역 선택하기
    brand_list = brands.find_elements(By.CSS_SELECTOR, '.swiper-slide')
    time.sleep(1)
    
    # 3. 브랜드명 가져오기
    brand = [brand_list[i].find_element(By.CSS_SELECTOR, 'dd.brand-ranking-card-name').text for i in range(len(brand_list))]
    result.append(brand)
import pandas as pd
df = pd.DataFrame(result, index=month_list, columns=week_list)
df

 

동적 웹 스크래핑

 

▶인스타그램 좋아요 클릭하기

# .env
ID = <My ID>
PASSWORD = <My password>
# !pip install python-dotenv
import os
from dotenv import load_dotenv

load_dotenv()

ID = os.getenv('ID')
PASSWORD = os.getenv('PASSWORD')
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

driver = webdriver.Chrome()
driver.get('https://instagram.com')
driver.maximize_window()
time.sleep(3)

input_id, input_password = driver.find_elements(By.TAG_NAME, 'input')
input_id.send_keys(ID)
input_password.send_keys(PASSWORD, Keys.ENTER)
time.sleep(3)

login_info = driver.find_element(By.CLASS_NAME, '_ac8f')
login_info.click()
time.sleep(3)

notice_btn = driver.find_element(By.CSS_SELECTOR, 'button._a9--._a9_1')
notice_btn.click()
time.sleep(3)

like_btn_list = driver.find_elements(By.CSS_SELECTOR, 'span.xp7jhwk')
for like_btn in like_btn_list:
    like_btn.click()
    time.sleep(3)

 

▶유튜브 영상 댓글 가져오기

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

driver = webdriver.Chrome()
driver.get('https://www.youtube.com/watch?v=8NjP0VUi3gQ')
driver.maximize_window()
time.sleep(3)
def scroll_down(num):
    for i in range(num):
        body = driver.find_element(By.TAG_NAME, 'body')
        body.send_keys(Keys.PAGE_DOWN)
import time
time.sleep(3)
scroll_down(20)
comments = driver.find_elements(By.CSS_SELECTOR, 'yt-formatted-string#content-text')
video_comments = [i.text for i in comments]
video_comments

API

▶API란?

- API(Application Programming Interface)란, 프로그램 간의 상호작용을 가능하게 하는 인터페이스

- 보통 웹 서비스에는 HTTP 요청을 통해 API를 호출하고, JSON 또는 XML 형태의 데이터를 응답합니다. API를 사용하면 서비스 개발 및 유지 보수를 더욱 용이하게 할 수 있음

- TV와 사용자를 연결해주는 것이 리모컨인 것처럼 API도 Database와 User를 연결해주는 리모컨의 역할을 한다고 생각하면 됨

▶인터페이스

- 인터페이스는 두 가지 다른 시스템, 장치 또는 프로그램 사이에서 상호작용이 가능하게 하는 접점을 의미함

- API 역시 두 시스템 간의 인터페이스 중 하나이며, 우리가 매일 사용하는 스마트폰의 터치스크린, 음성 비서, ATM기의 키패드, 공항 자동 발권기 등과 같은 것들도 인터페이스가 될 수 있음

- 이러한 인터페이스들은 User와 System 간의 상호작용을 가능하게 함

▶User ↔ API ↔ Database

- API는 데이터베이스와 서버와 함께 사용되며, 데이터베이스는 데이터를 저장하고 관리하기 위한 시스템

- 서버는 User가 요청하는 정보를 저장하고 관리하는 컴퓨터로, API는 서버에서 데이터베이스로 요청을 보내고, 데이터베이스에서 받은 데이터를 User에게 보내는 역할

- 예를 들어, 웹 애플리케이션에서 사용자가 로그인할 때, 서버는 데이터베이스에서 사용자 정보를 가져와 사용자가 올바른 정보를 입력했는지 확인하는데, 이러한 작업은 API를 통해 이루어짐

- 서버는 API를 통해 데이터베이스에 요청을 보내고, 데이터베이스는 요청을 처리하여 결과를 서버로 반환함

- 서버는 이러한 결과를 User에게 전달하여 로그인 작업을 완료함

→ 일반적으로 데이터를 수집하는 입장에서 보면 우리는 User(Client)가 되고, API를 개발하는 입장에서 본다면 Server쪽이 된다고 생각하면 됨

▶CRUD Method

- API는 데이터베이스나 시스템 내에서 데이터를 조작할 수 있는 CRUD(Create, Read, Update, Delete) 메소드를 제공함

- 이 메소드들은 데이터에 대해 수행할 수 있는 기본적인 작업들에 해당됨

① Create: 시스템 내에서 새로운 데이터를 생성할 때 사용. 일반적으로 생성할 데이터와 함께 API 엔드포인트로 POST 요청을 보내는 것을 포함

② Read: 시스템에서 데이터를 검색할 때 사용. 일반적으로 검색할 데이터를 지정하는 매개변수와 함께 API 엔드포인트로 GET 요청을 보내는 것을 포함

③ Update: 시스템 내에서 기존 데이터를 수정할 때 사용. 일반적으로 수정할 데이터와 함께 API 엔드포인트로 PUT 또는 PATCH 요청을 보내는 것을 포함

④ Delete: 시스템에서 데이터를 삭제할 때 사용. 일반적으로 삭제할 데이터를 지정하는 매개변수와 함께 API 엔드포인트로 DELETE 요청을 보내는 것을 포함

- 이러한 메소드들은 복잡한 작업을 수행하기 위해 조합하여 사용할 수 있음

- ex) Create 메소드를 사용하여 쇼핑카트에 새 항목을 추가하고, Read 메소드를 사용하여 카트 내용을 확인하고, Update 메소드를 사용하여 항목 수량을 수정하고, Delete 메소드를 사용하여 항목을 카트에서 제거할 수 있음

▶API 응답

- API를 호출하면 서버에서는 요청에 대한 응답으로 데이터를 반환

- 응답은 보통 JSON 또는 XML 형식으로 제공되며, 이 데이터를 사용하여 애플리케이션에서 필요한 작업을 수행할 수 있음음

- API 응답은 성공적으로 처리된 경우, 서버에서 HTTP 상태 코드 200을 반환

- 실패한 경우, HTTP 상태 코드와 함께 오류 메시지를 반환 → 이러한 오류 메시지를 통해 애플리케이션에서 오류를 처리할 수 있음음

- API 응답은 보통 캐싱을 지원하는데, 이를 통해 이전에 받은 응답을 캐시에 저장하여 다음 요청 시에는 캐시된 응답을 반환할 수 있음

→ 이를 통해 애플리케이션의 성능을 향상시킬 수 있음

▶JSON & XML

- API에서 응답으로 제공되는 데이터 형식으로는 주로 JSON과 XML이 사용됨

- JSON(JavaScript Object Notation)

① 자바스크립트에서 사용하는 객체 리터럴 문법을 따르는 경량화된 데이터 교환 형식

② JSON은 일반 텍스트 형식으로 구조화된 데이터를 전송하기 때문에, XML보다 더욱 간결하고 가벼움

③ JSON은 자바스크립트에서 사용되는 객체 리터럴 문법을 따르기 때문에, 자바스크립트에서 쉽게 파싱할 수 있음음

- XML(eXtensible Markup Language)

① 데이터와 데이터 구조를 기술하기 위한 마크업 언어

② XML은 더욱 다양한 데이터 형식을 지원하며, 데이터와 데이터 구조를 명확하게 기술할 수 있음음

- API 응답으로 제공되는 데이터 형식은 서비스 제공자와 이용자 양측 모두에게 중요한데, 이용자는 API 응답으로 제공되는 데이터 형식에 따라 데이터를 해석하고 처리할 수 있기 때문

- 따라서 서비스 제공자는 이용자가 쉽게 이해하고 처리할 수 있는 데이터 형식을 선택해야 함(최근에는 JSON 형식이 더욱 많이 사용되고 있음)

▶[실습] 서울 열린 데이터 광장

- 서울시 지하철 실시간 열차 위치 정보

# 요청
import requests
import pandas as pd

URL = 'http://swopenAPI.seoul.go.kr/api/subway/<내인증키>/json/realtimePosition/0/5/4호선'
response = requests.get(URL)
print(response)

# json 데이터 가져오기
json_data = response.json()

# key 확인
json_data.keys()

# 가져오기 위한 데이터 선택
data = json_data['realtimePositionList']

# 데이터 프레임으로 가져오기
df = pd.DataFrame(data)
df

- 서울시 기간별 일평균 대기환경 정보

API_KEY = '<YOUR_KEY>' # 자신의 인증키를 입력해주세요.
URL = f'http://openAPI.seoul.go.kr:8088/{API_KEY}/json/DailyAverageRoadside/1/5/20200315'

# get
import requests
response = requests.get(URL)

# json 데이터 가져오기
json_data = response.json()

# 가져오기 위한 데이터 선택
data = json_data['DailyAverageRoadside']['row']

# 데이터 프레임으로 가져오기
df = pd.DataFrame(data)
df.head()
 

▶[실습] 공공데이터포털

- 한국주택금융공사 전세자금대출 금리 정보(JSON)

import requests
import pandas as pd

API_KEY = '<YOUR_KEY>'

# BASE_URL = 'http://apis.data.go.kr/B551408/rent-loan-rate-info'
# END_POINT = '/rate-list'
url = 'http://apis.data.go.kr/B551408/rent-loan-rate-info/rate-list'
params ={'serviceKey' : f'{API_KEY}', 'pageNo' : '1', 'numOfRows' : '10', 'dataType' : 'json' }

response = requests.get(url, params=params)

json_data = response.json()

data = json_data['body']['items']

df = pd.DataFrame(data)
df.head()

- 한국관광공사_국문 관광정보 서비스_GW(JSON)

import requests

URL = 'http://apis.data.go.kr/B551011/KorService1/detailPetTour1'
params = {'serviceKey' : '<My key>',
          'MobileOS' : 'ETC',
          'MobileApp' : 'myApp',
          '_type': 'json'}
response = requests.get(URL, params=params)

json_data = response.json()
# URL 확인하기 1

from requests import Request, Session

s = Session()
req = Request('GET', URL, params=params)
prepped = s.prepare_request(req)

print(prepped.url)  # 준비된 요청의 URL 확인
# URL 확인하기 2
# URL 생성
request_url = URL + '?' + '&'.join([f'{key}={value}' for key, value in params.items()])
print(request_url)

 

- 한국관광공사_국문 관광정보 서비스_GW(XML)

! pip install lxml
import requests
import pandas as pd

URL = 'http://apis.data.go.kr/B551011/KorService1/detailPetTour1'
params = {'serviceKey' : '<My Key>',
          'MobileOS' : 'ETC',
          'MobileApp' : 'myApp',
          '_type': 'xml'}
response = requests.get(URL, params=params)

pd.read_xml(response.text, xpath='/response/body/items/item')

 

- 행정안전부_통계연보_연도별 지방자치단체 외국인 주민(XML)

import requests

URL = 'http://apis.data.go.kr/1741000/ForeignLocalGovernmentsYear/getForeignLocalGovernmentsYear'
params = {'ServiceKey' : '<My Key>'}
response = requests.get(URL, params=params)
print(response)
# URL로 구조 확인

from requests import Request, Session

s = Session()
req = Request('GET', URL, params=params)
prepped = s.prepare_request(req)

print(prepped.url)  # 준비된 요청의 URL 확인
import pandas as pd
pd.read_xml(response.text, xpath='/ForeignLocalGovernmentsYear/row')

  • OPEN AI API

▶ 텍스트 생성

- .env(비밀 파일 만들기) : ID나 PW, API Key를 저장해두는 용도로 쓰임

OPENAI_API_KEY = <My Key>

- ipynb 파일 : 응답 확인

from openai import OpenAI
client = OpenAI()
# system : 시스템의 역할
# user : 유저의 채팅
# assistant : GPT의 답변
messages = [
    {'role' : 'system', 'content' : 'You are a helpful assistant.'},
    {'role' : 'user', 'content' : '오후 5시에 듣기 좋은 노래 가사를 만들어줘'}
]
response = client.chat.completions.create(
    model = 'gpt-4',
    messages= messages,
    max_tokens= 1000, 
    temperature= 0.8
)

response.choices[0].message.content

- ipynb 파일 : 이전 답변 전달

from openai import OpenAI
client = OpenAI()
# system : 시스템의 역할
# user : 유저의 채팅
# assistant : GPT의 답변
messages = [
    {'role' : 'system', 'content' : '단답으로 간략하게 답변'},
    {'role' : 'user', 'content' : '겨울에 어울리는 음식은?'},
    {'role' : 'assistant', 'content' : '아이스크림'},
    {'role' : 'user', 'content' : '아이스크림과 함께 먹으면 좋은 것은?'},
    {'role' : 'assistant', 'content' : '과자'},
    {'role' : 'user', 'content' : '지금 먹을 간식 추천해줘'},
]
response = client.chat.completions.create(
    model = 'gpt-4',
    messages= messages,
    max_tokens= 1000, 
    temperature= 0.8
)

response.choices[0].message.content

'AI데이터 엔지니어, 새싹' 카테고리의 다른 글

80th_1_4(Thu)_RNN 주가예측  (0) 2024.01.08
77th_12_22(Fri)_Streamlit 활용  (0) 2024.01.08
70th_12_14(Mon)_시계열 데이터 분석  (0) 2024.01.08
73th_12_18(Mon)_Web Scrapping  (1) 2023.12.18
62th_121_Overfitting  (0) 2023.12.04