#!/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!")