본문 바로가기

개발이나하자../backend

[django] 파이썬 장고 BeautifulSoup 이용한 웹 크롤링 연습

간단한 크롤링 작업을 해보았다. 처음인데 재미있네.. 근데 이거 불법인가?

상업 아니고 그냥 연습이에요.. 

뭘 끌어올까 고민하다가 야구를 좋아해서 네이버 스포츠에서 점수를 크롤링 해보기로 했다.

제일 간단한거 먼저 해보고 기능은 추가해볼 예정

핑크색 박스에 있는 부분을 끌어오려고 한다.

 

간단한 장고로 이용한 크롤링

django는 당연히 있어야 하고

 

pip로 두 개 인스톨한다.

pip install BeautifulSoup

pip install requests

 

 

먼저 프로젝트를 생성한다.

django-admin startproject crawlingapp

 

 

crawlingapp 디렉터리로 들어간다.

cd crawlingapp

 

 

app 생성

python manage.py startapp baseball

 

 

settings.py 에서  생성한 baseball앱을 crawlingapp 프로젝트에 등록하기

 

 

baseball > urls.py 생성

여기서 urlpatterns 를 다른 단어로 하면 안된다. 무조건 urlpatterns 로 하세요

url_patterns로 바꿨더니 circulating url 뭐 어쩌고 하면서 에러 나서 한참 삽질했다 ㅠ

 

baseball > views,py 에서 score_board 함수 생성. 여기 안에서 크롤링 작업을 할 계획

 

crawlingapp > urls.py 에 baseball > urls.py 등록

 

즉 목표/프로세스는 아래와 같다.

localhost:8000/api/kbo/ 로 접속했을 때 

https://sports.news.naver.com/kbaseball/schedule/index.nhn?date=20200825&month=08&year=2020&teamCode=

여기서 오늘 경기 결과를 크롤링 해오려고 한다.

 

먼저 네이버 html 태그를 분석을 해야 한다.

크롬을 사용합니다.

Mac에서는 cmd + option을 누른 채 i를 누르면 개발자 도구가 열린다. 

아니면 오른쪽 마우스 클릭 > inspect (한글로는 검사... 인가?) 

 

 

이렇게 개발자 도구가 열린다. 그러면 맨 위에 elements 탭을 클릭하고 왼쪽에 있는 커서 버튼을 클릭한다.

 

 

커서 아이콘을 클릭하고 웹 페이지에서 원하는 부분에 마우스를 가지고 가면 하이라이트가 된다. 그리고 클릭을 하면 오른쪽에 해당 태그를 보여준다.

 

 

파란색 박스는 ul, 그리고 그 안에 핑크색 박스 하나하나는 li로 되어있다는 것을 확인할 수 있다.

 

그럼 내가 해야 하는 것은 

ul 태그를 뽑아 와서 그 안에 있는 li를 돌면서 데이터를 뽑아 오면 되겠다 라고 생각이 들어짐.

근데 이게 맞는 방법인지는 모르겠지만 일단 한다.

 

 

구조를 정리해 본다. ul 안에 li가 여러 개 (오늘 경기가 있는 만큼) 들어있다.

li 태그 안에는 div가 4개 들어있고

첫 번째 div 안에는 경기 상태 - 종료? 몇 회인지? 를 클래스 state를 통해 보인다.

두 번째 div 안에는 첫 번째 팀 이름과 점수

세 번째 div 안에는 두 번째 티 이름과 점수

네 번째 div 안에는 그냥 버튼들... 이건 나에게 필요 없는 것

<ul class="sch_vs" id="todaySchedule">
	<li class="end ">
		<div class="vs_cnt">
			<em class="state">종료</em>
		</div>
		<div class="vs_lft">
			<img width="46" height="46" alt="키움" title="키움" src="https://sports-phinf.pstatic.net/team/kbo/default/WO.png?type=f64_64" onerror="javascript:this.src='https://sports-phinf.pstatic.net/team/no_emblem_s_square.png';">
			<p class="vs_team">
				<strong>키움</strong>
				<span class="game_info"><span class="win">승</span><a target="_blank" href="http://www.koreabaseball.com/Record/Player/PitcherDetail/Basic.aspx?playerId=67313">브리검</a></span>
			</p>
			<strong class="vs_num">4</strong>
		</div>
		<div class="vs_rgt">
			<img width="46" height="46" alt="KT" title="KT" src="https://sports-phinf.pstatic.net/team/kbo/default/KT.png?type=f64_64" onerror="javascript:this.src='https://sports-phinf.pstatic.net/team/no_emblem_s_square.png';">
			<p class="vs_team">
				<strong>KT</strong>
				<span class="game_info"><span class="lose">패</span><a target="_blank" href="http://www.koreabaseball.com/Record/Player/PitcherDetail/Basic.aspx?playerId=50040">데스파이네</a></span>
			</p>
			<strong class="vs_num">1</strong>
		</div>
		<div class="vs_btn">
			<a class="btn_rst" href="https://sports.news.naver.com/gameCenter/gameResult.nhn?category=kbo&amp;gameId=20200825WOKT02020">경기결과</a>
			<a class="btn_vod" href="/gameCenter/gameVideo.nhn?category=kbo&amp;gameId=20200825WOKT02020">경기영상</a>
		</div>
	</li>
    
    <li>...</li>
    <li>...</li>
    <li>...</li>
</ul>
             

 

 

티스토리 코드 블록은 자주 깨지는 듯..ㅠㅠ 파이썬은 인덴트가 중요한데 그게 깨지니 코드를 알아보기가 어렵다..

버그 수정해주세요 ㅠ span 태그가 이상한데.. 아무튼!!!

def score_board(request):
	
    # 클롤링 할 웹 주소
	url = 'https://sports.news.naver.com/kbaseball/schedule/index.nhn?date=20200825&month=08&year=2020&teamCode='
    
    # pip install requests 를 사용한다.
    req = requests.get(url)
    
    # 전체 페이지 html 가지고 오기
    soup = BeautifulSoup(req.text, 'html.parser')
	    
    
    # 나는 아까 말 한 ul 태그를 가지고 오려고 하는데 그 ul 태그의 id 가 todaySchedule이고
    # ul 태그 안에 있는 모든 li를 today_schedule변수 안에 넣는다.
    today_schedule = soup.find('ul', {'id': 'todaySchedule'}).findAll('li')
    
    # 가지고 온 li를 반복문을 돈다.
    for schedule in today_schedule:
    	
        #  상태를 가지고 온다
        # <em class="state">종료</em> 라는 태그 안에 있는 종료 값을 가지고 오고
        # .strip()을 이용해서 앞 뒤 공백을 제거한다.
    	state = schedule.find('em', class_='state').text.strip()

		# <div class="vs_lft"></div> 태그를 찾는다
		left = schedule.find('div', class_='vs_lft') 
        
        # 팀 이름을 찾는다
		left_team = left.p.strong.text.strip()
        
        # 팀 점수를 찾는다.
		left_team_score = left.find('strong', class_='vs_num').text

		# 왼쪽과 동일하다. 
        right = schedule.find('div', class_='vs_rgt')
        right_team = right.p.strong.text.strip()
        right_team_score = right.find('strong', class_='vs_num').text
 
		print(state)
		print(left_team, left_team_score)
		print(right_team, right_team_score)
		print('----------------------------------')

return HttpResponse('')

 

print로 해서 terminal에 이렇게 나온다.

가공해서 json으로 만들거나 바로 template 랜더 해도 되지만 나중에..

일단 이렇게 간단하게 가지고 올 수 있다는 게 신기하네...

마침 크롤링 한 날에 NC가 이겨서 기분이 좋네욬ㅋ