크롤링과 스크레이핑
- 크롤링(Crawling): 인터넷의 데이터를 활용하기 위해 정보들을 분석하고 활용할 수 있도록 수집하는 행위이다.
- 스크레이핑(Scraping): 크롤링 + 데이터를 추출하고 가공하는 행위이다.
- 예제 1
import requests
from bs4 import BeautifulSoup
requests로 http요청을 보내고 받는 데 사용하는 라이브러리를 import 하여 html을 가져오는 데 사용한다.
BeautifulSoup은 웹페이지의 html을 파싱하고, 원하는 정보를 추출하기 위해서 사용한다.
site = "https://basicenglishspeaking.com/daily-english-conversation-topics/"
request = requests.get(site)
print(request)
# print(request.text) # text를 뽑을 수 있음
크롤링할 site를 정해서 넣어준다.
get 요청을 보내 사이트의 웹 페이지 내용을 가져온다. text를 사용하면 text값을 뽑을 수 있다.
soup = BeautifulSoup(request.text) # 파싱하기위한 객체
requests를 사용하여 가져온 html을 파싱하기 위한 객체 soup를 만들어준다.
divs = soup.find("div", {"class": "thrv-columns"}) # 겹치지 않게 뽑아주기
원하는 데이터를 뽑아주기 위한 코드이다. 웹 페이지에서 원하는 데이터만 뽑기 위해 태그를 찾으려면 해당 웹페이지에서 마우스 오른쪽 클릭을 하고 '검사'를 눌러주면 쉽게 찾을 수 있다.
links = divs.findAll('a') # a태그만 list로 가져옴
div안에 a태그만 list로 가져오려면 findAll을 사용하여 뽑아준다. 이때 뽑아준 links는 배열이 된다.
for link in links:
print(link.text)
반복문을 통해 a태그만 들어있는 배열의 text값을 뽑아주면

이런식으로 나온다.
subject = []
for link in links:
subject.append(link.text)
print('총', len(subject), '개의 주제를 찾았습니다.')
for i in range(len(subject)):
print("{0:2d}. {1:s}".format(i+1,subject[i]))

새로운 배열을 만들어서 값을 추가해 주고, 원하는 방식으로 뽑으면 된다. 위와 같은 결과가 나온다.
- 예제 2
# https://v.daum.net/v/20240520060022001
# https://v.daum.net/v/20240520052002727
# https://v.daum.net/v/20240520043039891
def daum_news_title(new_id):
url = "https://v.daum.net/v/{}".format(new_id)
request = requests.get(url)
soup = BeautifulSoup(request.text)
title = soup.find("h3", {"class": "tit_view"})
if title:
return title.text.strip()
return "제목없음"
daum_news_title("20240520052002727")
이건 뉴스기사에서 제목을 가져오는 코드를 작성한 것이다.
url에 들어있는 해당 뉴스기사의 code번호를 넣었을 때 기사의 헤드라인을 가져오는 것이다.
예제 1과 비슷한 방식으로 자신이 찾고 싶은 태그를 찾아서 반환해 주면 끝이다.
- 예제 3
# 1위 Supernova - aespa
# 2위 해야 (HEYA) - IVE (아이브)
request = requests.get("https://music.bugs.co.kr/chart")
soup = BeautifulSoup(request.text)
print(soup)
titles = soup.findAll("p", {"class": "title"})
artists = soup.findAll("p", {"class": "artist"})
for i, (t, a) in enumerate(zip(titles, artists)):
title = t.text.strip()
artist = a.text.strip().split("\n")[0]
print("{0:3d}위. {1:s} - {2:s}".format(i+1, title, artist))
이건 벅스 뮤직 차트에 있는 top100을 가져오는 코드를 작성한 것이다.
title과 artist가 들어있는 태그를 찾아 배열에 담아주고, 반복문을 통해서 text값을 원하는 방식으로 출력해 주면 된다.
- 예제 4
request = requests.get("https://www.melon.com/chart/index.htm")
print(request) # <Response [406]>
이번에는 멜론 차트를 가져오는 것인데, 요청에 대한 응답을 받을 수가 없다.
robots.txt라는 웹 사이트에 크롤러같은 로봇들의 접근을 제어하기 위한 규약이라는 것이 있다고 한다. 그래서 응답을 받을 수 없었다.
이 부분을 해결하려면 f12를 누르고 Network에서 index부분에 가장 밑에있는 User-Agent를 긁어온다.
# User-Agent:
# Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
request = requests.get("https://www.melon.com/chart/index.htm", headers=header)
soup = BeautifulSoup(request.text)
titles = soup.findAll("div", {"class": "rank01"})
artists = soup.findAll("span", {"class": "checkEllipsis"})
for i, (t, a) in enumerate(zip(titles, artists)):
title = t.text.strip()
artist = a.text.strip()
print("{0:3d}위. {1:s} - {2:s}".format(i+1, title, artist))
긁어온 User-Agent의 값을 headers로 넣어주면(전체 다 넣어줄 필요는 없음) 정상적으로 요청에 대한 응답을 받아올 수 있다. 그 이후는 위에 다른 예제들과 비슷하다.
- 예제 5
# https://finance.naver.com/item/main.naver?code=032800
# https://finance.naver.com/item/main.naver?code=053950
# 이름, 가격, 종목코드, 거래량
# {"name": "경남제약", "price": "1545", "code": "053950", "volume": "1828172"}
def naver_finance(code):
site = f"https://finance.naver.com/item/main.naver?code={code}"
request = requests.get(site)
soup = BeautifulSoup(request.text)
div_totalinfo = soup.find("div", {"class": "new_totalinfo"})
name = div_totalinfo.find("h2").text
div_today = div_totalinfo.find("div", {"class": "today"})
price = div_today.find("span", {"class": "blind"}).text
# div_description = div_totalinfo.find("div", {"class": "description"})
# code = div_description.find("span", {"class": "code"}).text
table_no_info = soup.find("table", {"class": "no_info"})
tds = table_no_info.findAll("td")
volume = tds[2].find("span", {"class": "blind"}).text
dic = {"name": name, "price": price, "code": code, "volume": volume}
return dic
naver_finance("032800")
codes = ["053950", "032800", "099220", "003230", "000660"]
data = []
for code in codes:
dic = naver_finance(code)
data.append(dic)
print(data)
이건 네이버 증권 페이지에서 이름, 가격, 종목코드, 거래량을 dic형태로 담아서 출력하는 코드이다.
이것도 위 예제를 잘 조합하면 만들 수 있는 간단한 코드이다.
내가 처음에 작성할때는 어떤 태그를 가져오는 게 좋을지 몰라서 print로 계속 확인하면서 했다.
import pandas as pd
df = pd.DataFrame(data)
df
# df.to_excel("naver_finance.xlsx")
위 코드는 pandas를 사용한 것인데, 데이터 프레임을 생성할 수 있다. 뿐만 아니라 생성된 데이터 프레임을 엑셀파일로 내보낼 수도 있다.
'Python > 데이터분석' 카테고리의 다른 글
Python seaborn, folium, 상권별 업종 밀집 통계 데이터 (0) | 2024.05.28 |
---|---|
Python 가상 온라인 쇼핑몰 데이터 (0) | 2024.05.28 |
Python MatPlotlib (0) | 2024.05.27 |
Python 넘파이(Numpy) (0) | 2024.05.22 |
Python 셀레니움 (0) | 2024.05.22 |