Python/데이터분석

Python 크롤링

dustKim 2024. 5. 21. 01:46
크롤링과 스크레이핑

 

- 크롤링(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