Python 크롤링 시스템에 SQLite 도입하기

임기범·2022년 7월 19일
0

오늘은 Python으로 크롤링 시스템을 구현하는 과정에서 DB 쿼리를 다루는 Python 라이브러리 두 가지(sqlite3, pymysql)를 사용해 보았다.
크롤링 로직을 최적화하기 위해 SQLitesqlite3 라이브러리를 어떻게 사용했는지에 대한 내용을 본 포스팅에 정리해 보았다.

개요

현재 개발 중인 크롤링 시스템에서, DB를 핵심적으로 사용하게 되는 요구사항은 다음과 같다.

  1. URL request를 전송할 때, 쿼리에 들어가는 숙박상품의 id가 유효한지를 파악해야 한다.
  2. html 문서를 파싱해 얻은 데이터를 저장해야 한다.

크롤링 타겟인 여기어때의 경우 각 숙박 상품이 1번부터 auto-increment 방식으로 id가 부여되어 있고, URL 쿼리에 이 id값을 변경시켜 request롤 보내면 id에 해당하는 숙박 상품의 html 문서를 가져올 수 있다. 따라서 id 값을 1부터 마지막 id까지 연속적으로 증가시키며 request를 전송하면 모든 숙박업체에 대한 정보를 가져오는 것이 가능하다.
하지만, 연속적으로 모든 id를 request로 전송하게 되면 숙소 정보가 삭제되는 등 유효하지 않은 id를 쿼리로 넣은 URL까지 전송되므로, 불필요한 작업이 반복적으로 수행된다.
이러한 문제점을 해결하기 위해, idvalidity 두 가지 칼럼을 가진 테이블을 로컬 DB에 생성하고, 각 id의 유효성을 저장하여 유효성을 가진 id에 대해서만 request를 전송하는 방식으로 구현한다. 나는 이 로직을 sqlite3 라이브러리를 통해 구현하였다.

SQLite

SQLite는 경량화된 DBMS 오픈 소스 소프트웨어로써, 서버가 아닌 응용 프로그램에 내장되어 동작하는 DBMS이다. 경량화된 DBMS를 표방하는 만큼, 가벼운 것이 가장 큰 특징이자 장점이라고 할 수 있겠다. SQLite DB는 Python 프로그램 내에서 sqlite3 라이브러리를 통해 쿼리를 수행하여 조작할 수 있다.

Python + sqlite3 으로 SQLite 조작하기

import sqlite3

connect = sqlite3.connect("resources/id.db") // db 파일 연결
cursor = connect.cursor()

cursor.execute("CREATE TABLE IdTable(id int, validity boolean)") // 테이블 생성 쿼리 수행

def exist(id):
    # execute select query 
    cursor.execute("SELECT * FROM IdTable WHERE id == (:id)", {"id" : id}) 
    # return True if id is fetched
    return cursor.fetchone() != None


def id_is_valid(id):
    # execute select query 
    cursor.execute("SELECT validity FROM IdTable WHERE id == (:id)", {"id" : id})
    # fetch validity and return it
    return cursor.fetchone()
    

for id in range(1, 71750):
    
    crawl_data(id, 1) 
    
    html = open(FILE_PATH_TEMPLATE % id, 'r').read()
    validity = not is_cannot_load(html)
    
    if exist(id):
    	# if id and validity is exist in DB, 
        # execute update query
        cursor.execute("UPDATE IdTable  SET validity=(:validity) WHERE ID=(:id)", {"id" : id, "validity" : validity})
    else:
    	# if id and validity is not exist in DB, 
        # execute insert query    
	    cursor.execute("INSERT INTO IdTable VALUES(:id, :validity)", {"id" : id, "validity" : validity})
    
    # commit
    connect.commit() 
profile
장래희망: 초고수 개발자

0개의 댓글