#1-7 경마 데이터 수집하기 - 다수의 경기를 SQLite3 DB에 저장하기

목차

    2017. 7. 28. 15:25

    다수의 경주 결과를 저장하기 위해서는 for문과 try, except 구문을 활용하는 것이 좋다. 여러 개의 데이터를 저장하기 위해 for문을 이용한다. 데이터를 저장하다가 에러가 발생하는 경우 멈추지 않고 다음 데이터로 넘어가기 위해서 예외처리를 할 수 있는 try, except 구문을 활용한다. SQLite3에 대해서 알고 싶다면 이전 포스팅을 참조하기 바란다.
    ( 참조: #1-6 경마 데이터 수집하기 - SQLite라는 DB로 저장하기 )


    코딩



    먼저 아래와 같이 ym이라는 list형태로 년월을 저장한다. 해당 년월들을 for문으로 작업할 예정이다.



    ym=list(["201201","201202","201203","201204","201205","201206","201207","201208","201209","201210","201211","201212",

             "201301","201302","201303","201304","201305","201306","201307","201308","201309","201310","201311","201312",

             "201401","201402","201403","201404","201405","201406","201407","201408","201409","201410","201411","201412",

             "201501", "201502", "201503", "201504", "201505", "201506", "201507", "201508", "201509", "201510","201511",

             "201512","201601","201602","201603","201604","201605","201606","201607","201608","201609","201610","201611",

             "201612","201701","201702","201703","201704","201705"])



    1. SQLite DB에 연결

    SQLite DB에 저장하기 위해 DB와 연결을 한다. 아래와 같이 입력하면 DB와 연결할 수 있다. SQLite에서는 DB가 파일로 저장된다. 'race_db_bu.db'라는 파일이 없어도 자동으로 생성이 된다. 

    연결을 한 이후에 해당 DB에 데이터를 저장하면 된다.


    con = sqlite3.connect("./data/race_db_bu.db")

    cursor = con.cursor()


    아래와 같이 for문을 이용해서 ym이라는 년월엘 날짜를 붙여준다. range 함수를 이용하면, 0부터 해당 list의 끝까지 for문을 돌릴 수 있다. 1,2,3일과 같이 날짜가 한 자리인 경우 앞에 0을 붙여서 url을 만들어 준다. 01, 02, 03과 같이 말이다.

    for day in range(1,32): 이 부분은 날짜를 2자리로 만들고 년월을 붙여서, 최종 날짜를 만들어 주는 부분이다.


    for a in range(len(ym)):
        for day in range(1,32):
            try:
                if day<10:
                    date=ym[a]+"0"+str(day)
                else:
                    date=ym[a]+str(day)


    다음은 각 날짜에 대해, for문을 돌린다. 경마는 하루에 보통 15경기가 열린다. 넉넉하게 1부터 20까지 for문을 돌린다. 그 다음 각 날짜와 경기번호에 대해 make_day_bu라는 함수를 실행해서 경기결과를 받아온다. 이것은 앞에서 경기결과를 수집하는 기능을 함수형태로 정의해 놓은 것이다.


    불러운 경기결과는 total이라는 데이터 프레임으로 저장된다. rider는 경기결과 중에 있는 벌치정보를 수집한 것이다. 



    2. to_sql함수를 이용해서 DB에 저장

    total에 경기결과가 수집되면, to_sql이라는 함수를 이용해 SQLite에 저장한다. 테이블명은 따옴표('')로 지정한 total_bu가 된다. if_exists='append'는 기존에 테이블이 있을 경우 그 뒤에 값을 붙이라는 옵션이다. 'replace'라는 값을 지정할 수도 있는데, 이렇게 지정하면 기존의 테이블을 삭제하고, 신규 테이블로 교체한다.

    혹은 cursor를 만들어서 SQL문을 이용해도 된다. 이 방법은 차후에 다뤄보도록 하겠다.


        for no in range(1,20):

            try:


                total, rider = make_day_bu(date,no)


                total.to_sql('total_bu', con, if_exists='append',index=False)

                rider.to_sql('rider_bu', con, if_exists='append',index=False)


                print("Success: "+date+","+str(no))


            except Exception as e:

                print("Failed: " + date + "," + str(no), end=", ")

                print(e)

                break



    3. DB 연결 종료

    SQLite에 DB작업이 완료되면, DB를 닫는 작업을 하는 것이 좋다. DB를 닫는 명령은 아래와 같다.


    con.close()


    for문을 실행하면, 15번째 이후의 경기 데이터를 수집하려고 할 떼 에러가 발생한다. 하루에 14경기가 있다고 하면 수집할 데이터가 없기 때문이다. 하지만, try&except문을 이용해서 예외처리를 하였기 때문에, 에러 발생시 예외처리구문을 실행하고 계속 데이터를 수집할 수 있다. 이상이 없을 때는 try문을 잘 실행하고 error가 발생하면 except문으로 넘어간다. 


    except로 넘어오면 print 명령을 이용해 어느 날짜에서 에러가 났는지, 그리고 에러의 사유가 무엇인지 출력하고, break 문을 이용해 for문을 빠져 나온다. for문을 빠져나오면 그 다음 날짜의 경기를 탐색하게 된다.


    이렇게 다수의 경주결과를 저장하였다. 그리고 경주 결과를 크롤링하실 때는 금,토,일은 피하는 것이 좋다. 이 날은 경마 경기가 있는 날이라 페이지 접속 속도도 낮고, 계속 싸이트에 접속할 경우 서버 공격으로 오인받아 IP가 차단될 수 있다. 그리고 IP가 차단되시면 렛츠런파크에 전화해서 풀어달라고 하면 된다.

    하지만, 이 글을 보고 크롤링(crawling) 하기에는 시간이 많이 소요될 것이다. 그래서 필자가 크롤링한 DB를 다음 포스팅에 올려 놓았다.