python 버전은 3.7이며, requests와 bs4 라이브러리를 외부에서 다운받아야 합니다. (가상환경을 사용하면 쉬움)
예제로 만든 코드는 네이버 영화에서 영화 순위, 이름, 변동여부, 변동등수를 가져오는 코드입니다.
https://movie.naver.com/movie/sdb/rank/rmovie.nhn
랭킹 : 네이버 영화
영화, 영화인, 예매, 박스오피스 랭킹 정보 제공
movie.naver.com
****** 한글이 깨지는 경우
encoding을 'UTF-8'로 해도 깨지는 경우에는
file = open( ~, encoding = 'euc-kr')을 하면 해결됩니다.
1. 전체 코드
import requests
from bs4 import BeautifulSoup
import csv
class Scraper ():
#크롤링할 url을 초기값으로 설정
def __init__(self):
self.url = "https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=cnt&tg=0&date="
#url에 연결해서, beautifulsoup을 이용해서 정렬된 soup데이터로 리턴.
def get_html(self, date):
res = requests.get(self.url+str(date))
if res.status_code != 200:
print("Request Error : ", res.status_code)
html = res.text
soup = BeautifulSoup(html, 'html.parser')
return soup
#등수 변동이 na, up, down으로 제공되기 때문에, = + -로 변경합니다.
def change_direction(self, L):
if L == 'na':
L = '='
elif L == 'up':
L = '+'
else:
L = '-'
return L
#순위 데이터를 가져와서, 이름, 변동여부, 변동등수를 가져와서 csv파일에 저장합니다.
def get_data(self, soup, date):
#순위 데이터를 가져오자
listRanking = soup.find(class_ = "list_ranking")
movieName = []
movieUpdown = []
movieNum = []
#tr태그를 찾아서 각 tr태그에서 tit3, arrow, range ac를 가져옵니다
for tr_tag in listRanking.find_all('tr'):
tag = tr_tag.find(class_='tit3')
if tag:
movieName.append(tag.text.replace("\n",""))
updown = tr_tag.find(class_='arrow')
if updown:
movieUpdown.append(self.change_direction(updown["alt"]))
num = tr_tag.find(class_='range ac')
if num:
movieNum.append(num.text)
self.write_csv(date, movieName, movieUpdown, movieNum)
#CSV파일로 저장합니다. UTF-8을 사용하면, 한글이 깨지기때문에, euc-kr형식으로 저장합니다.
def write_csv(self, date, movieName, movieUpdown, movieNum):
#파일은 데이터 추가, newline 시 공백 추가
file = open("movieRank.csv", "a", newline="", encoding = 'euc-kr')
wr = csv.writer(file)
for i in range(len(movieName)):
wr.writerow([str(date), str(i + 1), movieName[i], movieUpdown[i], movieNum[i]])
file.close()
#movieRank라는 csv파일을 생성하고, 날짜마다 한번씩 크롤링해옵니다.
def scrap(self, startdate, finishdate):
#처음에 실행할 때는 w로 실행하여, 기존의 데이터가 있으면 초기화
file = open("movieRank.csv", "w", newline = "", encoding = 'euc-kr')
wr = csv.writer(file)
wr.writerow(["Date","Rank.", "Name", "UpDown", "Change_Amount"])
file.close()
for i in range(finishdate - startdate +1):
soup = self.get_html(startdate + i)
self.get_data(soup, startdate + i)
위처럼 클래스를 만든 후, 다음과 같이 실행하면 끝.
s = Scraper()
s.scrap(20200413,20200414)
2. 코드 부분 설명
1) 데이터 불러오기
requests.get(url)을 하면, 해당 페이지를 불러옵니다.
제대로 연결되었다면, status = 200입니다.
사이트 상태에 따라 다양한 에러가 발생할 수 있기 때문에, 연결되지 않으면 Error code를 출력하도록 합시다.
html을 res.text로 가져오고, Beautifulsoup(html, "html.parser")를 이용해서 데이터를 바꿔줍시다.
그러면 다음과 같이 깔끔하게 정리된 html형식의 데이터가 나옵니다.
2) 필요한 데이터만 골라서 크롤링하기
크롤링에서 핵심 부분입니다.
html에서 태그와 클래스를 찾아서 데이터를 가져오는 것이 메인이기 때문에, 많이 해보는 것이 실력이 가장 빨리 는다고 하네요
크롬 기준으로 도구 더보기 - 개발자도구 - Element에서 html을 이용해서, 크롤링할 부분을 선택합시다.
Elements 왼쪽으로 두번째에 있는 것을 누르면, 쉽게 부분을 고를 수 있습니다.
전체 데이터에서 table 태그가 달려있고, class이름이 'list_ranking'인 곳을 가져옵시다.
list_ranking 속에서 tr태그로 순위 데이터들이 나열되어 있는 것을 알 수 있습니다.
따라서, list_ranking.find_all('tr')을 해서 모든 tr데이터를 가져옵니다.
tr태그 내에서 'ac', 'title', 'ac', 'range ac'로 구분됩니다.
더 자세히 보면, class = tit3가 제목, class = arrow가 화살표, class = range ac가 변동폭입니다.
따라서, tit3.text를 하면 영화제목, range ac.text를 하면 변동폭입니다.
ac의 경우 na라는 데이터를 가져와야 하기 때문에, arrow["alt"]를 하면 내부 데이터를 가져올 수 있습니다.
데이터가 빈칸이 경우에는 None값이기 때문에, if tag 를 써서 None인 경우는 pass해주면 됩니다.
위와 같은 과정을 for문으로 날짜별로 반복시켜주면, 날짜마다 순위 데이터를 구할 수 있습니다.
그 뒤는 write_csv를 하면 됩니다.
실행 결과는 다음과 같이 나옵니다.
'Python > NLP(자연어처리)' 카테고리의 다른 글
4. 텍스트 전처리(정규화) (0) | 2020.09.04 |
---|---|
3. khaiii 설치 및 사용법 (0) | 2020.09.03 |
2. konlpy 사용법 (0) | 2020.09.02 |
1. 임베딩이란 (0) | 2020.09.01 |