본문 바로가기

Codestates AI 부트캠프/4. Data Engineering

[데이터 엔지니어링] 2-2. Crawling

1. 웹페이지 구조

  • HTML : 구조와 뼈대를 잡는다
  • CSS : 겉모양을 꾸며준다 
  • Java Script : 기능을 할 수 있게 만든다

a. HTML

HyperText Markup Language. MDN에 의하면 프로그래밍 언어가 아니다. 웹페이지의 구성을 표시하는 마크업 언어. 

head, body, div, li 등의 태그를 통해 구성과 요소를 표시한다. 태그들 사이에는 python 클래스처럼 부모-자식 관계가 존재한다.

 

# 예시
# <li> 태그는 <ul> 태그의 자식 태그다

<ul>
    <li>Hello</li>
    <li>World</li>
    <li>!</li>
</ul>

 


1-2. CSS

Cascading Style Sheets. CSS는 웹페이지가 어떻게 표현되는 지 알려주는 스타일시트 언어. 

  • 주요 개념 : selector, 상속, class 

2. Web Crawling

웹을 돌아다니며 정보를 수집하는 행위. 수집을 원하는 페이지의 HTML 정보를 긁어와 내가 원하는대로 정리하는 과정이다.

robot.txt에 들어가면 해당 사이트의 크롤링 허용 여부를 알 수 있다. 사이트 내 정보마다도 허용 여부가 다를 수 있다. 허용되지 않은 데이터를 긁어오면 법적인 이슈로 이어질 수 있으니 꼭 조심하도록 하자!

a. 주요 사용 라이브러리

  • requests : python과 url을 연결하고 html 정보를 긁어온다
  • bs4 : 긁어온 html 정보를 parsing하고 원하는 데이터만 추려낸다
  • selenium : log in, page down 등 웹에서 마우스나 키보드로 해야할 일을 코드로 자동화한다

b. 크롤링 과정

① 페이지 HTML 정보 긁어오기

 

import requests

url = "https://www.weather.go.kr"
page = requests.get(url)

# 응답 확인
page.status_code

# 내용 확인
page.text


이때 응답은 세자리수 번호로 출력된다. 정상적으로 응답을 받았다면 200번이 출력된다. 아래 링크에서 번호별 응답이 무엇을 뜻하는 지 알 수 있다.
https://developer.mozilla.org/ko/docs/Web/HTTP/Status

② Parsing

 

from bs4 import BeautifulSoup
soup = BeautifulSoup(page.content, 'html.parser')


③ Select

이제 사이트 내에서 원하는 것만 뽑아보자. F12을 눌러 개발자 도구를 킨 다음 왼쪽 상단 마우스 모양을 누르면 원하는 부분의 HTML 구조를 알 수 있다. 
 
그 후 해당 부분에 아래와 같이 copy SELECTOR를 통해 태그를 뽑아올 수 있다

 

 

# 원하는 데이터 추려내기
source = soup.select("#lnb > div.tab > div.tab-item.on > div > ul > li")

 

select 대신에 find, find_all을 쓸 수도 있다. find와 find_all에서는 태그, class, id, 문자열 등을 통해 검색할 수 있다.

 

# find : 조건에 일치하는 첫번째 결과 리턴
dog_element = soup.find(id='dog')

# find all : 조건에 일치하는 모든 결과 리턴
cat_elements = soup.find_all('div', class_='cat')

# 위 코드로 찾은 결과물을 다시 세부적으로 검색
for cat_el in cat_elements:
    cat_el.find(class_='fish')

# 문자열로 검색하기
soup.find_all(string='raining')

# 대소문자 구분없이 문자열로 검색하기
soup.find_all(string=lambda text: 'raining' in text.lower())


④ 데이터 정리

select와 find로 원하는 데이터를 가져온 후, 정리를 해야한다. 먼저 가져온 정보에서 text만 꺼낸다. 그리고 '.strip()' '.split('\n')'과 같은 메서드를 써서 깔끔하게 만들 수 있다. 리스트 안에 넣어줄 수도 있다.

 

# text만 꺼내기
only_text = source.text

# text만 꺼내서 리스트에 넣기
my_list = [i.text for i in source]

# text만 꺼내서 불필요한 띄어쓰기 정리하기
cat_el.text.strip()