import re # 정규식 표현식 사용
import sqlite3 # 기본 데이터 베이스 사용
from urllib.request import urlopen # 사이트 접근하기 위해 사용
from html import unescape # html 태그 제거 용도
def main():
"""
함장 테일러이다.
여기는 브릿지이며
모든 컨트롤은 여기서 한다.
"""
#작전 구역은 이곳이다.
url_base = 'http://www.yes24.com/24/category/bestseller'
#작전 구역에 침투하여 그들이 사용하는 encode가 무엇인지 탐색한다.
html = charsets(url_base) # 탐색후 그 값을 html에 저장합니다.
#탐색 완료후 작전구역에 침투하여 정보를 습득하다.
best_books = scraping(html) # 습득한 html값을 best_books에 리스트로 저장합니다.
# 1급기밀 저장소를 확보한다.
save('yes24.db',best_books) # save(데이터베이스 이름, 리스트(best_books)))
# 요청한 기밀 자료를 제공한다.
load('yes24.db')
def charsets(url_base):
"""
작전구역을 탐색하는 곳이다.
어떤 규격의 언어를 사용하는 찾아내야된다.
못찾을 경우도 대비해야 작전성공률을 높일수 있다.
utf-8 or cp949 등 규격을 알아내야된다.
"""
plan = urlopen(url_base) # 작전 구역으로 들어갑니다.
#작전명이 무엇인지 파악합니다. 불분명할시 utf-8 코드네임으로 강제전환합니다.
encoding = plan.info().get_content_charset(failobj='utf-8')
# 암호를 해독합니다.
# 이것은 html = plan.read().decode('utf-8')등과 같습니다.
html = plan.read().decode(encoding)
return html # 정보를 알려주고 빠져나옵니다.
def scraping(html):
"""
작전수행중입니다.
모든 정보를 수집합니다.
"""
yes24_best = [] # 수집한 정보를 보관합니다.
ranking = 0 # 정보수집의 목적에 따라 사용되었습니다.현재는 순서입니다.
# re.findall은 '정해진 모든것을 찾아라' 이며 찾은값을 보내줍니다.
# r''은 이스케이문자의 사용을 편하게 합니다.
# re.findall(r'조건', 대상 , 추가명령) 여기선 re.DOTALL사용('\n'도 포함시킴)
# re.search() 사용도 위와 동일하며 정해진 구역의 아무곳을 찾아서 값을 돌려줍니다.
# re.sub()는 조건을 다른 조건으로 바꿉니다. replace()와 비슷합니다.
# unescape()는 html 태그를 없애고 나머지 값을 돌려줍니다.
for yes_best in re.findall(r'<p class="copy"><a.*?</p>',html,re.DOTALL):
url = re.search(r'<a href="(.*?)">',yes_best).group(1)
url = 'http://yes24.com' + url
ranking += 1
title = re.sub(r'<.*?>','',yes_best)
title = unescape(title)
yes24_best.append({'ranking':ranking ,'url':url,'title':title})
return yes24_best
def save(db,best_books):
"""
1급보안구역
데이터 베이스 저장구역
관계자외 출입금지
"""
conn = sqlite3.connect(db) #데이터베이스를 연결합니다.save(db)를 받아서 사용합니다.
cur = conn.cursor() # db제어권을 가져옵니다.
cur.execute('DROP TABLE IF EXISTS yes24best') # 같은 이름테이블이 있으면 삭제합니다.(재사용)
#테이블을 구성합니다.
cur.execute('''
CREATE TABLE yes24best (
ranking int,
title text,
url text
)
''')
# excutemany 사용시 리스트형식의 자료를 db로 보낼수 있습니다.(books))
cur.executemany('INSERT INTO yes24best VALUES (:ranking, :title, :url)',best_books)
conn.commit() # 자료를 제출합니다.
conn.close() # db를 닫습니다.
def load(db):
"""
요청에 따라 정보를 제공합니다.
"""
conn = sqlite3.connect(db)
cur = conn.cursor()
cur.execute('SELECT * FROM yes24best') #자료를 불러옵니다.
for row in cur.fetchall(): # 불러들인 자료를 출력합니다.
print(row)
conn.close()
if __name__=="__main__": # 테스트 도구 - 시험작동 됩니다.
main()