네이버 웹툰 크롤러를 만들었는데 로그인 된 세션이 아니다보니 나이제한 걸린 웹툰 접근이 안됐다.
네이버 로그인 구현을 하려고 검색을 해보니 역시 선구자가 있었다.
원리는 잘 모르겠으나 일단 잘 읽어보고 시도. 옛날 소스라 특히 encode, decode를 좀 수정해줘야 한다.
파이썬 문법도 잘 모르는데 옛날 소스 포팅하려고 하니 이건 뭐 장님 코끼리 만지는 격이다.
다 수정해서 돌렸는데 로그인을 하니 status code는 200 OK가 나오는데 자꾸 캡차가 나온다.
여기서 requests 대신 selenium을 써볼까 했는데 속도가 너무 느려서 포기했다.
좀 더 찾아보니 또 역시나 선구자가 있었다.
요약하면 bvsd.js 파일에서 브라우저 정상/비정상 여부를 감지해 캡차를 띄운다는 것. 어짜피 클라이언트에서 감지하는 것이니 우회할 수 있는데 위 소스들이 vb.net, c#이라 베끼는 데 좀 애를 먹었다 ㅠ
그리고 보니까 public key 주소도 변경됐다.
이전
http://static.nid.naver.com/enclogin/keys.nhn
현재(2020. 3. 16 기준)
https://nid.naver.com/login/ext/keys.nhn
import re
import uuid
import requests
import rsa
import lzstring
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter
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)
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))
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
if __name__ == "__main__":
s = naver_session('idid', 'pwpw')
print(1)
pp = s.get('https://comic.naver.com/webtoon/detail.nhn?titleId=726095&no=42')
print(pp)
완성한 소스 예제. 아이디랑 비밀번호 하드코딩돼있다.
naver_session 함수 중간에 Retry가 들어가있는데 크롤링할 때 쓰려고 한거라 빼도 된다. 로그인 후에는 네이버 웹툰에서 성인 만화 한 화에 접속해 로그인이 됐는지 확인한다.
위 소스로 로그인이 잘 안될 수 있는데, 이때는 response 확인해봐야한다. 아이디 보호모드? 그런게 나오면 해제를 해줘야 한다.
위 소스로 로그인했을 때 캡차가 나오면 로그인 루틴이 바뀐 것일 확률이 높다.
+ 2020. 06. 11
프로젝트를 깃허브에 올려놨습니다 (링크)
일단 동작은 잘 합니다. 문서화가 겁나 부실하고 리팩토링이 하나도 안돼있는데.. 동작은 합니다. 코딩테스트 준비한답시고 손도 못댔네요.
후우~ 이번주 안에 시간내서 프로젝트를 다듬어야겠습니다. 혹시 사용법이 궁금하면 댓글 달아주세요
'프로그래밍 > Python' 카테고리의 다른 글
[Python] 문자열 뒤집기 (0) | 2020.10.31 |
---|---|
Python3 typing.Optional (0) | 2020.08.07 |
Python3 기본 자료형(Built-in Types) (0) | 2020.03.17 |
Python3 json dump 한글 깨짐 해결방법 (0) | 2020.03.14 |
Python3 pip로 lxml 라이브러리 설치가 안될 때 (0) | 2020.03.14 |