Skip to content

Instantly share code, notes, and snippets.

@theeluwin
Created February 23, 2020 06:41
Show Gist options
  • Save theeluwin/b5234cc50fb0b2f59556e9619c01cb9c to your computer and use it in GitHub Desktop.
Save theeluwin/b5234cc50fb0b2f59556e9619c01cb9c to your computer and use it in GitHub Desktop.
곰자막 다운로드 스크립트 (죄송해요 곰앤컴퍼니 여러분)
# -*- 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