- DrugImg.DIK_CODE 44자 Base64 image key 가능성 문서화 - 평문 DIK_CODE 직접 join 단정 제거 - health.kr zoom 후보 URL과 실제 이미지 GET 검증 스크립트 추가
97 lines
3.4 KiB
Python
97 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Probe PIT/PM drug image key assumptions.
|
|
|
|
This script is intentionally read-only. It does not require production credentials in the repo;
|
|
wire `query_rows()` to pyodbc/pymssql in your environment.
|
|
"""
|
|
from __future__ import annotations
|
|
import base64
|
|
import hashlib
|
|
import json
|
|
import re
|
|
import urllib.request
|
|
import urllib.error
|
|
from dataclasses import dataclass
|
|
|
|
|
|
def classify_key(value: str) -> dict:
|
|
value = value or ''
|
|
out = {'value': value, 'length': len(value), 'kind': 'unknown'}
|
|
if re.fullmatch(r'\d{13}', value):
|
|
out['kind'] = 'plain_13_digit_dik_code'
|
|
return out
|
|
try:
|
|
raw = base64.b64decode(value, validate=True)
|
|
out['base64_bytes'] = len(raw)
|
|
out['base64_hex_prefix'] = raw[:8].hex()
|
|
if len(value) == 44 and len(raw) == 32:
|
|
out['kind'] = 'base64_32byte_digest_like_key'
|
|
else:
|
|
out['kind'] = 'base64_other'
|
|
except Exception:
|
|
out['kind'] = 'non_base64_text'
|
|
return out
|
|
|
|
|
|
def sha256_b64_candidates(plain: str) -> dict:
|
|
return {
|
|
enc: base64.b64encode(hashlib.sha256(plain.encode(enc)).digest()).decode()
|
|
for enc in ['utf-8', 'cp949', 'utf-16le']
|
|
}
|
|
|
|
|
|
def probe_url(url: str, referer: str | None = None, timeout: int = 10) -> dict:
|
|
headers = {'User-Agent': 'Mozilla/5.0'}
|
|
if referer:
|
|
headers['Referer'] = referer
|
|
try:
|
|
req = urllib.request.Request(url, headers=headers)
|
|
with urllib.request.urlopen(req, timeout=timeout) as r:
|
|
head = r.read(32)
|
|
return {
|
|
'url': url,
|
|
'ok': True,
|
|
'status': r.status,
|
|
'content_type': r.headers.get('content-type'),
|
|
'content_length': r.headers.get('content-length'),
|
|
'head_hex': head.hex(),
|
|
'is_jpeg': head.startswith(b'\xff\xd8\xff'),
|
|
}
|
|
except Exception as e:
|
|
return {'url': url, 'ok': False, 'error': f'{type(e).__name__}: {e}'}
|
|
|
|
|
|
def extract_zoom_image_candidates(dik_code: str) -> dict:
|
|
url = f'https://www.health.kr/drug_info/sb/zoom.asp?drug_code={dik_code}'
|
|
result = {'zoom_url': url, 'ok': False, 'candidates': []}
|
|
try:
|
|
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
|
|
with urllib.request.urlopen(req, timeout=15) as r:
|
|
data = r.read(300000)
|
|
# health.kr pages are usually euc-kr/cp949-ish.
|
|
text = data.decode('euc-kr', errors='replace')
|
|
result['ok'] = True
|
|
imgs = re.findall(r'''(?:src|myImg\.src)\s*=\s*['\"]([^'\"]+)''', text, flags=re.I)
|
|
paths = re.findall(r'''https?://[^'\"<>\s]+(?:sb_photo|big3|marked3)[^'\"<>\s]+''', text, flags=re.I)
|
|
result['candidates'] = sorted(set(imgs + paths))
|
|
except Exception as e:
|
|
result['error'] = f'{type(e).__name__}: {e}'
|
|
return result
|
|
|
|
|
|
def demo():
|
|
# Replace these with real rows from PM_DRUG..CD_GOODS and PM_IMAGE..DrugImg.
|
|
plain_dik = '2015012700008'
|
|
image_key = 'xiY4jUZTAZB0p8JpHEa+Zt9DEcOVQFq9sgtAxSG7GXY='
|
|
print(json.dumps({
|
|
'plain_dik': classify_key(plain_dik),
|
|
'image_key': classify_key(image_key),
|
|
'sha256_plain_candidates': sha256_b64_candidates(plain_dik),
|
|
'direct_big3': probe_url(f'http://pharm.or.kr/images/sb_photo/big3/{plain_dik}.jpg'),
|
|
'zoom_candidates': extract_zoom_image_candidates(plain_dik),
|
|
}, ensure_ascii=False, indent=2))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
demo()
|