Files
bin/naver_campaign.py
rozbrian 304cbcc554 update
2026-01-10 20:46:22 +09:00

128 lines
4.5 KiB
Python
Executable File

#!/usr/bin/python3
import os
import re # 정규 표현식 모듈
import uuid # 고유 식별자 생성 모듈
import requests # HTTP 요청을 처리하는 모듈
import rsa # RSA 암호화 알고리즘 모듈
import lzstring # LZ-String 압축 알고리즘 모듈
from urllib3.util.retry import Retry # HTTP 요청 재시도를 위한 모듈
from requests.adapters import HTTPAdapter # HTTP 어댑터
import time # 시간 처리 모듈
from bs4 import BeautifulSoup # HTML/XML 파서
from urllib.parse import urljoin # URL 조합 함수
# 주어진 키와 사용자 정보를 이용하여 암호화하는 함수
def encrypt(key_str, uid, upw):
# 문자열을 조합하는 함수
def naver_style_join(l):
return ''.join([chr(len(s)) + s for s in l])
# 암호화 키 분리 및 정수 변환
sessionkey, keyname, e_str, n_str = key_str.split(',')
e, n = int(e_str, 16), int(n_str, 16)
# 메시지 조합 및 인코딩
message = naver_style_join([sessionkey, uid, upw]).encode()
# 공개키 생성 및 메시지 암호화
pubkey = rsa.PublicKey(e, n)
encrypted = rsa.encrypt(message, pubkey)
return keyname, encrypted.hex()
# 사용자 계정을 암호화하는 함수
def encrypt_account(uid, upw):
key_str = requests.get('https://nid.naver.com/login/ext/keys.nhn').content.decode("utf-8")
return encrypt(key_str, uid, upw)
# 네이버 세션 생성 함수
def naver_session(nid, npw):
encnm, encpw = encrypt_account(nid, npw)
# HTTP 세션 설정
s = requests.Session()
retries = Retry(total=5, backoff_factor=0.1, status_forcelist=[500, 502, 503, 504])
s.mount('https://', HTTPAdapter(max_retries=retries))
request_headers = {'User-agent': 'Mozilla/5.0'}
# 인증 데이터 생성 및 압축
bvsd_uuid = uuid.uuid4()
encData = '{"a":"%s-4","b":"1.3.4","d":[{"i":"id","b":{"a":["0,%s"]},"d":"%s","e":false,"f":false},{"i":"%s","e":true,"f":false}],"h":"1f","i":{"a":"Mozilla/5.0"}}' % (bvsd_uuid, nid, nid, npw)
bvsd = '{"uuid":"%s","encData":"%s"}' % (bvsd_uuid, lzstring.LZString.compressToEncodedURIComponent(encData))
# 로그인 요청 및 최종 URL 접속
resp = s.post('https://nid.naver.com/nidlogin.login', data={'svctype': '0', 'enctp': '1', 'encnm': encnm, 'enc_url': 'http0X0.0000000000001P-10220.0000000.000000www.naver.com', 'url': 'www.naver.com', 'smart_level': '1', 'encpw': encpw, 'bvsd': bvsd}, headers=request_headers)
finalize_url = re.search(r'location\.replace\("([^"]+)"\)', resp.content.decode("utf-8")).group(1)
s.get(finalize_url)
return s
# 네이버 캠페인 링크를 찾는 함수
def find_naver_campaign_links(base_url, visited_urls_file='/tmp/visited_urls.txt'):
# 방문한 URL 파일에서 읽기
try:
with open(visited_urls_file, 'r') as file:
visited_urls = set(file.read().splitlines())
except FileNotFoundError:
visited_urls = set()
# 기본 URL에 대한 요청
response = requests.get(base_url)
soup = BeautifulSoup(response.text, 'html.parser')
# 'list_subject' 클래스를 가진 span 요소 찾기 및 'a' 태그 추출
list_subject_links = soup.find_all('span', class_='list_subject')
naver_links = []
for span in list_subject_links:
a_tag = span.find('a', href=True)
if a_tag and '네이버' in a_tag.text:
#print(a_tag['href'])
naver_links.append(a_tag['href'])
# 캠페인 링크를 저장할 리스트 초기화
campaign_links = []
# 각 네이버 링크 확인
for link in naver_links:
full_link = urljoin(base_url, link)
if full_link in visited_urls:
print(link + " already visited!")
continue # 이미 방문한 링크는 건너뛰기
res = requests.get(full_link)
inner_soup = BeautifulSoup(res.text, 'html.parser')
# 캠페인 URL로 시작하는 링크 찾기
for a_tag in inner_soup.find_all('a', href=True):
if a_tag['href'].startswith("https://campaign2-api.naver.com"):
campaign_links.append(a_tag['href'])
# 방문한 링크 추가
visited_urls.add(full_link)
# 방문한 URL 파일에 저장
with open(visited_urls_file, 'w') as file:
for url in visited_urls:
file.write(url + '\n')
return campaign_links
# 시작할 기본 URL
base_url = "https://www.clien.net/service/board/jirum"
# 메인 실행 부분
if __name__ == "__main__":
s = naver_session(os.getenv('NAVER_ID'), os.getenv('NAVER_PWD'))
campaign_links = find_naver_campaign_links(base_url)
if(campaign_links == []):
print("All links visited.")
else:
for link in campaign_links:
print(link + "to be visited")
response = s.get(link)
#print(response.text) # 디버깅용
response.raise_for_status()
time.sleep(5)
print(link + " done!")