[파이썬] 웹(OP.GG) 스크래핑하기
개요
한 번도 해본 적 없는 크롤링을 한번 해보았다. 유명 게임 리그 오브 레전드의 전적 검색 사이트인 OP.GG에서 웹 크롤링을 해보았다.
플레이상 탑 정글 미드 원딜 서폿들의 승률 티어 데이터 정보를 30분 주기로 스크래핑하여 DB에 저장하는 것까지 시도해보았다..
사용한 라이브러리
BeautlfulSoup :
HTML정보로 부터 원하는 데이터를 가져오기 쉽게,
비슷한 분류의 데이터별로 나누어주는(parsing) 파이썬 라이브러리
selenium:
다양한 브라우저 맟 플랫폼에서 웹 응용 프로그램을 위한 무료 자동화 테스트 스위트
webdriver
sqlalchemy:
SQLAlchemy는 인기 있는 SQL 툴킷이며 Object Relational Mapper이다. 이것은 파이썬으로 작성되었고 응용 프로그래머에게 강력한 기능과 풍부한 SQL의 유연성을 제공한다. MIT 라이선스에 따라 출시된 오픈 소스 및 크로스 플랫폼 소프트웨어
pandas:
Pandas는 쉽고 직관적인 관계형 또는 분류된 데이터로 작업할 수 있도록 설계된
빠르고 유연하며 표현이 풍부한 데이터 구조를 제공하는 Python 패키지
pymysql:
MySQL을 Python에서 사용할 수 있도록 하는 라이브러리
apscheduler:
특정시간에 주기적으로 프로그램을 실행시키는 스케줄러
이번 프로그램에선 단일 프로세스 실행이므로 BLockingScheduler 사용
과정
플레 이상 탑 정글 미드 원딜 서폿들의 승률 정보 티어를 알려면
https://www.op.gg/champions?region=kr&tier=platinum_plus&position=
이제 뒤에 top jungle mid adc sup들을 더해주면 각각의 정보를 불러올 수 있다


저 뽀삐 카밀 나서스 쉔 등등 의 정보는 table에 담겨있는데 tbody로 잘라서 그 안에 태그들을 활용하여 값을 받아오면 dataframe에 저장 후 sql로 db에 저장합니다
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from sqlalchemy import create_engine
import sqlalchemy
import time
import pandas as pd
import pymysql
from apscheduler.schedulers.blocking import BlockingScheduler
def get_Counter(counter):
if counter is None:
return 'None'
else:
return counter.get('src')
def crawl_Daily():
options = Options()
options.add_experimental_option('detach', True) # 브라우저 바로 닫힘 방지
options.add_experimental_option('excludeSwitches', ['enable-logging']) # 불필요한 메시지 제거
##크롭 드라이버 자동업데이트 및 설치
service = Service(ChromeDriverManager().install())
##DB연결 엔진 설정
sqlEngine = create_engine('mysql+pymysql://root:1111@localhost/test', pool_recycle=3600)
##db 테이블 설정
dtypesql = {'rank':sqlalchemy.types.INT,
'champImg':sqlalchemy.types.TEXT,
'champion':sqlalchemy.types.VARCHAR(20),
'tier':sqlalchemy.types.INT,
'winRate':sqlalchemy.types.VARCHAR(10),
'pickRate':sqlalchemy.types.VARCHAR(10),
'banRate':sqlalchemy.types.VARCHAR(10),
'counter1':sqlalchemy.types.TEXT,
'counter2':sqlalchemy.types.TEXT,
'counter3':sqlalchemy.types.TEXT,
}
base_url = "https://www.op.gg/champions?region=kr&tier=platinum_plus&position="
key=['top','jungle','mid','adc','support']
for k in range(len(key)):
search_url = base_url + key[k] ## 검색하는 진짜 url
driver = webdriver.Chrome(service=service, options=options)
driver.get(search_url)## 크롬드라이버에 url 넣고
html = driver.page_source
soup = BeautifulSoup(html, "html.parser") ##bs4에 html 넣고
items = soup.select("tbody")##tbody로 짜른다
driver.quit()
rows=items[0].find_all('tr') ## 찾아온 데이터에서 tr태그 찾아옴
champData=[0 for i in range(len(rows))]## tr태그 갯수만큼 챔프 데이터 가져옴
j=0
for row in rows: ##for each문
rank=row.find('td',class_='css-3bfwic e1oulx2j4').find('span').get_text() ##순위보여주는 td태그
champ=row.find('td',class_='css-cym2o0 e1oulx2j6') ##챔피언 정보를 담고있는 td태그
img=champ.find('img').get('src')## 챔피언 이미지
champName=champ.find('strong').get_text() ## 챔피언 이름을 가지고있는 strong태그
tier=row.find('td',class_='css-ew1afn e1oulx2j3').get_text() ##티어를 가지고있는 td태그
rate=row.find_all('td',class_='css-1wvfkid exo2f211') ## 승률,픽률,밴률을 담고있는 td태그
winRate=rate[0].get_text() ## 승률
pickRate=rate[1].get_text() ## 픽률
banRate=rate[2].get_text() ## 밴률
counter=row.find('td',class_='css-8jdpx8 e1oulx2j2') ## 카운터 챔피언 3개 아미지
counterC=[0 for i in range(3)]
## Counter챔피언이 존재를 할수도있고 3개가 아닌 수도있어서 예외처리
for i in range(3):
try:
counterC[i]=get_Counter(counter.find_all('img')[i])
except:
counterC[i]=None
## champdata에 정보 저장
champData[j]=[rank,img,champName,tier,winRate,pickRate,banRate,counterC[0],counterC[1],counterC[2]]
j=j+1
##DataFrame 사용 정렬
data=pd.DataFrame(champData,columns=['rank','champImg','champion','tier','winRate','pickRate','banRate','counter1','counter2','counter3'])
tableName=key[k]+"champ"
##db커넥
dbConnection = sqlEngine.connect()
try:
##db에 존재하는 테이블이면 replace시키고 data DB에 저장
frame = data.to_sql(name=tableName, con=dbConnection, if_exists='replace',index=False,dtype=dtypesql);
except ValueError as vx:
print(vx)
except Exception as ex:
print(ex)
else:
print("Table %s created successfully."%tableName);
finally:
dbConnection.close()
sched=BlockingScheduler()
##분당 함수 호출
sched.add_job(crawl_Daily,'interval',minutes=1)
## 스타트
sched.start()

느낀 점:
간단하지만 내가 원하는 정보를 뽑는 웹 스크래핑을 해보았다. 사실 위 코드는 너무 비효율적인 코드인 것 같다. 내가 파이썬을 오랫동안 했었다면 좀 더 정교하게 짯을텐데 하루 만에 공부하고 구현하느라 어려움이 많았다.
이제 다음으로 파이썬 파일을 AWS ec2에 올려서 진짜 주기적으로 db에 올리는 작업을 해보아야겠다.