축구선수 몸값 분석 웹 크롤링 (3) - 서버 연동하기

https://wikidocs.net/book/4479

 

핵심만 해보는 flask 튜토리얼

가끔씩 flask쓰려면 헷갈려서 필요한 것만 실전형으로 해보는 튜토리얼을 만들어봅니다. 개인적으로 할 때마다 구글링하는데, 이 방법말고 예전에 이게 더 편했는데..하던 ...

wikidocs.net

위 자료를 클론 코딩하며 키워드 분석 프로젝트를 배포까지 진행하였고,

이를 바탕으로 Flask를 활용한 사이드 프로젝트를 진행하였다.

 

1. 트랜스퍼 마켓 크롤링 파일 생성

from bs4 import BeautifulSoup
import requests
import pandas as pd
import time

def show_valueList(list_num):
    list_num = int(list_num)
    url = "https://www.transfermarkt.com/"

    headers = {'User-Agent' : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"}
    player_list=[]
    
    # url의 page 부분을 변수로 처리하여 반복문 실행
    for i in range(1,int(list_num/25)+1):
        url = f"https://www.transfermarkt.com/spieler-statistik/wertvollstespieler/marktwertetop?ajax=yw1&page={i}"

        r = requests.get(url, headers=headers)

        # BeautifulSoup()으로 웹페이지 분석하기
        soup = BeautifulSoup(r.text, 'html.parser')
        # 선수들의 정보가 담긴 태그와 클래스 찾기
        player_info = soup.find_all('tr', class_ = ['odd','even'])

        # player_info에서 'td' 태그만 모두 찾기
        for info in player_info:
            player = info.find_all("td")
        # 해당 정보를 찾아서 각 리스트에 추가하기
            number = player[0].text 
            name = player[3].text 
            position = player[4].text 
            age = player[5].text 
            nation = player[6].img['alt'] 
            team = player[7].img['alt'] 
            value = player[8].text.strip()
        # 데이터에서 숫자만 가져오기 (인덱싱)
            value = value[1:-1] # ex. €160.00m 에서 €이 [0]이고 m이 [-1] 
        
            player_list.append([number, name, position, age, nation, team, value])
    
        time.sleep(1)  # 1페이지 당 sleep
        
    # pd.DataFrame()으로 저장하기
    df = pd.DataFrame(player_list, 
        columns=['number', 'name', 'position', 'age', 'nation', 'team', 'value'])

    return df


if __name__ == "__main__":
    show_valueList(100)
  • 이전에 진행하던 코드를 옮겨왔으며, 입력 값에 따라( 25, 50, 75, 100) 몸 값 차트를 크롤링한다.
  • 추후 입력 값 범위를 늘릴 예정

2. Flask 서버 연결

from flask import Flask, render_template, request
import pandas as pd
import transfermarkt

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route("/list", methods=['POST'])
def post():
    value = request.form["number"]
    df = transfermarkt.show_valueList(value)
    return df.to_html()


if __name__ == "__main__":
    app.run(debug=True)
  •  virtualenv를 통해 가상환경에서 진행하였고, 1번 파일 transfermarkt.py를 import함.
  • 첫 index.html에서 입력을 받은 뒤, "/list" url로 연결되어 크롤링한 결과를 html로 변환하여 출력한다.
  • POST 방식으로 통신하였으며, index에서 입력받은 number 인자를 넘겨주었다.
  • post()에서 return 값을 표시하지 않거나, pandas 데이터 값이 반환될 경우 오류가 발생한다.

3. 첫 화면, Index.html

Document

전 세계 축구선수 몸값 보기

  • 선수 리스트 수를 입력한 만큼의 인원이 출력된다.

4. 출력 화면, 입력 값 : 25

etc-image-0

5. 문제 해결

  • 트랜스퍼마켓 실제 사이트에선 1페이지 당 25명을 출력하기 때문에 입력한 값에 해당하는 만큼의
    페이지만 가지고 와야 한다. 따라서 입력한 값을 25로 나누어 Int로 변환하여 반복문을 작성함.
  • 크롤링 모듈에서 가져온 값을 서버 모듈에서 실행하기 위해선 특정 url로 연결하여 메서드를 실행해야 하는데
    이 때의 리턴 값이 DataFrame일 경우 출력이 안되는 에러가 발생함. 따라서 이를 해결하기 위해 html로 변환하는
    방법을 찾게 되었고, 이를 적용하여 해결함.