[TIL] 25.02.27 API 및 웹 크롤링

2025. 2. 27. 21:41·실무형 데이터 분석가 양성 교육

Prologue

API 및 웹 크롤링으로 데이터를 수집하는 2번째, 3번째 방법을 배웠고 그 내용을 기록할게요.

API


전체 과정

  1. URL로 웹사이트에 접근
  2. 파라미터 전달
  3. XML이나 HTML 값을 리턴 받기
  4. XML을 Element로 파싱
  5. Element를 통해 데이터프레임(딕셔너리 = {열 이름: 값 리스트}) 만들기

Requse로 XML 받기

API로 통신 = HTTP 통신
HTTP 통신하는 방법이 파이썬에서는 requests 모듈로 구현되어있음
우리는 데이터를 받기만 할거임(get 메소드만 사용)
데이터 추가(Post), 수정(Put), 삭제(Delete)는 이미 API 제공자가 해두셨음

  1. Url, Parameters 전달(허락받은 사용자라는 것을 인증하는 Service Key도 Parameters에 포함)
# 실제 공공데이터 '전기자동차 충전소 정보' api로 가져오기

import requests

url = "http://apis.data.go.kr/B552584/EvCharger/getChargerInfo"
params = {'ServiceKey' : 'API 제공처에게 요청해서 받기'
          ,'pageNo' : '1'
          ,'numOfRows' : '10'
          }
response = requests.get(url, params)
display(response.text)

Url = 요청주소(필수, API 제공자와 요청자가 만나는 장소)
Params = 요청변수(필수도 있고 옵션도 있음)
-> 출력결과(response)

response의 속성을 통해 원하는 정보 조회

response.text: UTF-8로 인코딩된 문자열, xml 라이브러리를 통해 XML 객체로 바꿔야 함.
response.status_code: get 메서드에 대한 반응, 정상 작동(200)했는지 비정상 작동(4또는 5로 시작하는 숫자)했는지 알 수 있음

XML 파싱

  • BeautifulSoup을 통해 계층구조 확인
# response 예쁘게 확인
# !pip install beautifulsoup4 
# !pip install lxml # xml 데이터를 파싱해주기 위해 설치
from bs4 import BeautifulSoup
import lxml

# XML 파싱
soup = BeautifulSoup(response.text, 'xml')

# Pretty XML 출력
pretty_xml = soup.prettify()
print(pretty_xml)
  1. beautifulsoup을 설치하면 beautifulsoup3가 설치되니 조심. 꼭 4를 붙이자
  2. 설치 후 vscode 재시작을 통해 커널을 초기화 시킨다. 그래야 lxml을 인식함
    아래 이미지를 다음 사진처럼 예쁜 구조로 변경 가능

  • XML을 Element 객체로 파싱
    # XML 파싱: 문자열(text) -> XML 트리 구조조
    import xml.etree.ElementTree as ET
    

root = ET.fromstring(pretty_xml)

first_item = root.find(".//item")

dictionary = {child.tag.strip(): [] for child in first_item}
dictionary


1. ET 라이브러리를 통해 문자열을 XML 트리 구조로 바꾸면 XML의 태그 검색이 가능 -> 키 값과 열을 찾아서 DF로 만드는 과정을 코딩으로 할 수 있게됨
2. root는 XML 형태가 된 text 파일. XML 파일.
3. find(.//item)를 통해 첫번째 item 태그를 찾을 수 있음
.은 노드를 의미, /는 깊이를 의미, / 하나만 쓰면 바로 아래 계층에서만 찾고 // 두 개 쓰면 노드의 모든 하위 태그를 뒤져서 item을 찾음
4. df으로 만들 dictionary 생성, child tag를 키, 값은 [] 리스트로 만듦
.strip()은 문자열 양 쪽의 공백을 제거, 문자열의 공백은 제거하지 않음

### 딕셔너리에 값 채우기
```python
# XML의 태그 값을 딕셔너리 값에 넣기
import pandas as pd

for item in root.findall('.//item'):
    for i in item:
        dictionary[i.tag].append(i.text)

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


df에 값이 채워져있지만 \n이 양쪽에 붙어있음

앞 뒤 \n 제거

# 앞 뒤 \n 제거
df = df.map(lambda x: x.replace("\n", "").strip() if isinstance(x, str) else x)

display(df.loc[0, 'addr'], df.head(3))

(apply)map(lambda x: ~)를 통해 모든 셀에 함수를 적용
replace 함수를 통해 \n을 공백으로
참고: 위키독스, 파이썬노트
isinstance(x, str)을 통해 문자열에만 적용
str, list, int, float 등은 파이썬 내 자료형 클래스이므로 따옴표를 사용하지 않음

Spark 2주차

병렬 처리와 분산 처리

메모리가 감당 가능하다면 굳이 Spark 사용X, 연산을 최적화해야 함
파이썬에서는 멀티 쓰레딩이 아닌 멀티 프로세싱이 일반적임

  • 멀티 프로세스는 독립된 메모리 공간을 가지고, 멀티 쓰레딩은 같은 메모리 공간을 공유함

파이썬에서 병렬 처리 패키지: Joblib
밥 한 번 먹고와야할 시간을 커피 한 잔 가져오는 시간 안에 끝내게 할 수 있음
약간 비효율적인 부분을 보완하려면 multiprocessing 패키지 사용, 다만 어려움

  • 비효율적인 부분: 모든 코어가 작업이 끝나야 다 같이 그 다음 작업으로 넘어감

스파크 실습1

메모리를 효율적으로 사용하기

쓰지 않는 주피터 노트북, 크롬 등 파일은 끄기
함수를 사용하여 일시적으로 변수를 만들고 함수가 종료되면 그 변수를 삭제하기
함수가 실행되는 동안에만 메모리를 사용함

def extract_csvs():
    res = []
    for path in tqdm(glob("../app_review_data/*.csv")):
        app_name = path.split("/")[-1].replace(".csv", "")
        df_temp = pd.read_csv(path)
        df_temp = df_temp.assign(app_name=app_name)
        res.append(df_temp)
    df = pd.concat(res)
    return df

함수 내에서 선언된 app_name, df_temp등의 변수는 함수가 종료되면 삭제되고 출력값만이 나오게 된다.

폴더 내 파일 모두 하나의 df로 합치기

  1. glob으로 모든 .csv파일 선택
    from glob import glob
    glob("../app_review_data/*.csv")
    .. 모든 상위 디렉토리
    app_review_data 폴더 내의

*.csv: 모든 파일명 끝에 .csv가 있는 파일들의
파일 경로를 리스트로 만들어줌

  1. 모든 파일명의 파일을 하나로 통합
    def extract_csvs():
     res = []
     for path in tqdm(glob("../app_review_data/*.csv")):
         app_name = path.split("/")[-1].replace(".csv", "")
         df_temp = pd.read_csv(path)
         df_temp = df_temp.assign(app_name=app_name)
         res.append(df_temp)
     df = pd.concat(res)
     return df
    for 반복문의 리스트를 tqdm의 인자로 넣어서 진행률을 바에 표현되게 한다.
    app_name 열을 만들어주기 위해 각 파일명을 .csv를 빼고 읽은 후..
    csv를 읽어서 df로 만든 후
    df.assign(app_name=값)을 통해 app_name 컬럼을 생성하고 값을 채운다.
    df['app_name'] = 값과 같음
    pd.concat(리스트=res)로 모든 df를 합침

'실무형 데이터 분석가 양성 교육' 카테고리의 다른 글

[TIL] 25.03.06 Postgre SQL 코드 테스트 대비  (0) 2025.03.06
[TIL] 25.03.05 SQLD와 SQL 그리고 구미시 버스 프로젝트 시작  (0) 2025.03.05
[TIL] 25.02.26 데이터 분석가 취업 고민 및 조언 정리  (0) 2025.02.27
[TIL] 25.02.25 프로젝트 발표 및 회고  (0) 2025.02.25
[TIL] 25.02.24 실전 프로젝트 종료  (0) 2025.02.25
'실무형 데이터 분석가 양성 교육' 카테고리의 다른 글
  • [TIL] 25.03.06 Postgre SQL 코드 테스트 대비
  • [TIL] 25.03.05 SQLD와 SQL 그리고 구미시 버스 프로젝트 시작
  • [TIL] 25.02.26 데이터 분석가 취업 고민 및 조언 정리
  • [TIL] 25.02.25 프로젝트 발표 및 회고
건벌써
건벌써
비전공자가 빅데이터 분석가가 되려고 노력하는 과정을 솔직하게 차곡차곡 남기겠습니다.
  • 건벌써
    비전공자 빅데이터 분석가 되기
    건벌써
  • 전체
    오늘
    어제
    • 분류 전체보기 (28)
      • Data Scientist (2)
      • 취업지원 (1)
      • 영어 (0)
      • 실무형 데이터 분석가 양성 교육 (24)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    스파르타 코딩클럽
    PostgreSQL
    버스도착시간
    배달의민족
    태블로
    피그마
    Geopandas
    구미버스
    프로젝트 기획
    웹크롤링
    웹 크롤링
    API
    문제의식
    데이터무결성
    selenium
    빅데이터
    SQL
    데이터 분석가
    프로젝트회고
    좌표매핑
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
건벌써
[TIL] 25.02.27 API 및 웹 크롤링
상단으로

티스토리툴바