Created
February 23, 2020 06:41
-
-
Save theeluwin/b5234cc50fb0b2f59556e9619c01cb9c to your computer and use it in GitHub Desktop.
곰자막 다운로드 스크립트 (죄송해요 곰앤컴퍼니 여러분)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf -*- | |
import os | |
import time | |
import logging | |
import argparse | |
import requests | |
from bs4 import BeautifulSoup | |
LIST_URL = 'https://www.gomlab.com/subtitle/' | |
PAGE_URL_TEMPLATE = 'https://www.gomlab.com/subtitle/view.gom?seq={seq}' | |
DOWNLOAD_URL_TEMPLATE = 'https://www.gomlab.com/subtitle/download.gom?seq={seq}' | |
def parse_args() -> argparse.Namespace: | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--seq_file', type=str, default='last_seq.txt', help="마지막 작업 번호를 저장할 파일") | |
parser.add_argument('--log_file', type=str, default='gom.log', help="로그 파일") | |
parser.add_argument('--save_dir', type=str, default='files', help="저장할 디렉토리 경로") | |
parser.add_argument('--sleep_success', type=float, default=0.5, help="성공식 휴식 시간 (초단위, 예: 0.5)") | |
parser.add_argument('--sleep_fail', type=float, default=0.05, help="실패시 휴식 시간 (초단위, 예: 0.05)") | |
parser.add_argument('--min_text_length', type=int, default=1000, help="파일 최소 길이 (예: 1000)") | |
args = parser.parse_args() | |
args.log_name = args.log_file.split('.')[0] | |
return args | |
def get_logger(name: str, filepath: str) -> logging.Logger: | |
logger = logging.getLogger(name) | |
logger.setLevel(logging.INFO) | |
handler = logging.FileHandler(filepath) | |
handler.setLevel(logging.INFO) | |
logger.addHandler(handler) | |
return logger | |
def get_latest_seq() -> int: | |
res = requests.get(LIST_URL) | |
if res.status_code != 200: | |
raise Exception("최신 번호 확인 불가: 홈페이지 접속 안됨") | |
soup = BeautifulSoup(res.content, 'html.parser') | |
try: | |
href = soup.select('.container .tbl tbody tr:first-child td')[1].a.attrs['href'] | |
queries = href.split('?')[1].split('&') | |
for query in queries: | |
key, value = query.split('=') | |
if key.lower() == 'seq': | |
return int(value) | |
except ValueError: | |
raise Exception("최신 번호 확인 불가: 홈페이지 파싱 실패") | |
except TypeError: | |
raise Exception("최신 번호 확인 불가: 홈페이지 파싱 실패") | |
except IndexError: | |
raise Exception("최신 번호 확인 불가: 홈페이지 파싱 실패") | |
except KeyError: | |
raise Exception("최신 번호 확인 불가: 홈페이지 파싱 실패") | |
def get_last_seq(filepath: str) -> int: | |
try: | |
with open(filepath) as fp: | |
try: | |
seq = int(fp.read().strip()) | |
except ValueError: | |
seq = get_latest_seq() | |
except TypeError: | |
seq = get_latest_seq() | |
except FileNotFoundError: | |
seq = get_latest_seq() | |
return seq | |
def put_last_seq(filepath: str, seq: int) -> None: | |
with open(filepath, 'w') as fp: | |
fp.write(str(seq)) | |
def download_one_gom( | |
logger: logging.Logger, | |
seq: int, | |
save_dir: str, | |
min_text_length: int = 1000) -> bool: | |
# 이미 했는지 확인 | |
os.makedirs(save_dir, exist_ok=True) | |
save_path = os.path.join(save_dir, f'{seq}.smi') | |
if os.path.isfile(save_path): | |
logger.info(f"[{seq}] 이미 했음") | |
return False | |
# 페이지 존재 여부 확인 | |
page_url = PAGE_URL_TEMPLATE.format(seq=seq) | |
page_res = requests.get(page_url) | |
if page_res.status_code != 200: | |
logger.info(f"[{seq}] 존재하지 않는 페이지") | |
return False | |
# HTML 파싱 | |
soup = BeautifulSoup(page_res.content, 'html.parser') | |
try: | |
lang = soup.select('.tr_media')[-1].select('td')[0].text | |
except IndexError: | |
logger.info(f"[{seq}] HTML 파싱 실패") | |
return False | |
# 언어 확인 | |
if lang != "한국어" and lang.lower() != 'english': | |
logger.info(f"[{seq}] 한국어 혹은 영어가 아님") | |
return False | |
# 파일 다운로드 시도 | |
download_url = DOWNLOAD_URL_TEMPLATE.format(seq=seq) | |
download_res = requests.get(download_url) | |
if download_res.status_code != 200: | |
logger.info(f"[{seq}] 파일 없음") | |
return False | |
# HTTP 헤더 확인 | |
cd = download_res.headers.get('Content-Disposition') | |
if cd is None: | |
logger.info(f"[{seq}] HTTP 헤더 안맞음") | |
return False | |
# 파일 포맷 확인 | |
try: | |
ext = cd.split(';')[-1].strip().strip('"')[-3:].lower() | |
except IndexError: | |
logger.info(f"[{seq}] 확장자 해석 불가") | |
return False | |
if ext != 'smi': | |
logger.info(f"[{seq}] 확장자가 SMI가 아님") | |
return False | |
# 파일 길이 확인 | |
if len(download_res.text) < min_text_length: | |
logger.info(f"[{seq}] 너무 짧은 파일") | |
return False | |
# 저장 | |
with open(save_path, 'w') as fp: | |
fp.write(download_res.text) | |
logger.info(f"[{seq}] 성공") | |
return True | |
def entry(args: argparse.Namespace) -> None: | |
logger = get_logger(args.log_name, args.log_file) | |
seq = get_last_seq(args.seq_file) | |
while seq > 0: | |
succeed = download_one_gom(logger, seq, args.save_dir, args.min_text_length) | |
if succeed: | |
time.sleep(args.sleep_success) | |
else: | |
time.sleep(args.sleep_fail) | |
seq -= 1 | |
put_last_seq(args.seq_file, seq) | |
if __name__ == '__main__': | |
args = parse_args() | |
entry(args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment