안수찬의 개발이야기

Mechanize를 이용한 네이버 카페 출석수 올리기

Introduction

안수찬 @dobestan

안수찬 @dobestan

소프트웨어 생태계에 기여할 수 있는 실용주의 프로그래머가 되고자 합니다. 나는 안수찬이다. 그러므로 나는 할 수 있다.


Mechanize를 이용한 네이버 카페 출석수 올리기

Posted by 안수찬 @dobestan on .
Featured

Mechanize를 이용한 네이버 카페 출석수 올리기

Posted by 안수찬 @dobestan on .

네이버 카페 출석수 올리기 스크립트는 현재 동작하지 않습니다. 로그인까지는 동작하나 실제로 카페에 접속을 한 경우에 출석수가 오르지 않습니다. 아래의 과정을 참고만 하시기 바랍니다. 감사합니다.

개발을 시작하고 가장 유용(?)한 것 중에 하나가 "내가 필요한 스크립트"를 빠르게 짤 수 있게 되었다는 것이다. 지금까지 그냥그냥 사용했던 것 중에 유용했던 것을 꼽자면,

  • 멜론 실시간 음악을 크롤링해서, 그 타이틀 + 가수명 그대로 유투브 음원을 다시 한번 크롤링해서 그냥 카페에서 실시간 음악 무료로 듣기 스크립트 ( 사실 스크립트는 아니고 레일즈로 만들기는 했는데 ... )
  • 뽐뿌 휴대폰 장터 / 휴대폰 포럼 / 휴대폰 뽐뿌 게시판에서 "갤럭시 S5"라는 텍스트가 포함된 게시글이 올라오면 이메일로 알려주는 루비 스크립트
  • 서울대학교 조경학과 홈페이지에 새로운 게시글이 올라오면 이메일로 알려주는 루비 스크립트

등이 있었던 것 같다. 최근에는 네이버 카페 <중*나라>에서 열심히 물건을 판매하고 있다. 물건을 판매하면서 가장 중요한 것이 신뢰도인 것 같은데 출석수나 거래 이력이 많지는 않다보니 판매하는데 약간의 어려움이 있었다.

그래서 매우 "정상적이고 합법적인" 방법을 통해 출석수를 늘려서 등업을 하기로 결정했다.

네이버 카페 출석수 조건

일단 네이버에서 발표하는 공식적인 자료는 찾을 수 없었다. 하지만 검색을 해보니 접속한 이후 아무런 활동없이 30분 후에 접속을 하면 출석수가 오른다는 것을 발견할 수 있었다. 그리고 수동으로 간단하게 테스트를 해보았는데 실제로 이런 방식으로 (이론상으로는) 하루에 48회까지 로그인을 할 수 있다는 것을 확인했다.

30분에 한번씩 로그인해서 카페에 접속하면 출석수를 올릴 수 있다.

목표

  • ( 매번 Ruby로만 만들어서 ) 이번에는 Python으로 한번 만들어보기
  • CLI로만 모든 기능이 동작해야한다. ( 스크립트니깐 당연한 말이겠지만, 가장 큰 이유는 놀고 있는 EC2 서버를 사용하기 위해서이다. 매번 내 로컬 머신에서 동작하면 안된다. )
  • 스크립트는 최대한 간단하게 만들고 리눅스에 기본적으로 내장되어 있는 crontab을 이용해서 반복하기 ( crontab 한번 사용해보고 싶었는데 딱히 사용할 일이 별로 없어서 이번 기회에 사용하면서 사용법 익히기 )

Requirments

네이버 카페 출석수 올리기 스크립트를 활용하기 위해서는 네이버에서 제공하는 보안 기능 중 일부를 꺼 두어야 합니다. 당연하게도 이중장금번호, OTP 로그인 등의 이중 보안 장치들은 다 꺼두셔야 합니다.

1. 로그인 차단 설정

타지역 로그인 차단, 해외 로그인 차단을 모두 OFF로 변경해주셔야 합니다. 물론 평소에 사용하던 로컬 머신을 사용하신다면 ON으로 해주셔도 상관은 없지만 저는 개인적으로 AWS EC2 Tokyo에 있는 서버를 사용할 예정이기에 로그인 차단 설정은 사용하지 않도록 설정했습니다.

로그인 차단 설정을 ON으로 해두고 스크립트로 로그인을 시도하면 로그인이 차단되었다는 메시지와 함께 로그인이 되지 않습니다. 또한 아래처럼 메일로 알림이 오게 됩니다. ( 제 아이디와 IP는 가려두었습니다. ) 저같이 처음에 모르고 계속 시도하시면 계속 차단되어서 앞으로는 로그인할때 계속 인증번호(?)를 입력해야하는 매우 귀찮은 사태가 발생하실 수도 있습니다.

2. 새로운 기기 로그인 알림

사실 [새로운 기기 로그인 알람] 기능은 전혀 신경쓰지 않고 있다가 멀티 계정으로 테스트해보고서야 이 기능이 ON되어 있는 경우에 로그인이 되지 않는 문제를 찾았습니다. ( 로그인이 안된다기 보다는 쿠키를 받아오지 않아 추후에 카페 접속을 해도 출석수가 오르지 않습니다. )

이 기능을 ON으로 해둔 상태로 웹 브라우져로 로그인을 시도하면 아래와 같은 팝업이 뜨게 됩니다. 그런데 여기에서 문제는 "Save"나 "Don't Save"를 누르기 이전에는 사용자 세션에 대한 쿠키를 저장하지 않습니다. 따라서 스크립트에서 이 부분까지 컨트롤해주기에는 조금 과하다고 판단하여 그냥 이 보안 기능은 끄기로 결정했습니다.

네이버 로그인 살펴보기

위의 보안 설정을 다 끝낸 후에 가장 만만하게 살펴볼 수 있는 페이지는 네이버에서 제공하는 로그인 페이지였습니다 : http://nid.naver.com/nidlogin.login

필요없는 부분을 제외하고 살펴보면 frmNIDLogin이라는 form안에 id, pw에 값을 채우고 submit하면 성공적으로 로그인이 될 것 같았습니다.

<form id="frmNIDLogin" name="frmNIDLogin" action="https://nid.naver.com/nidlogin.login" method="post">  
    <input type="text" id="id" name="id" placeholder="아이디">
    <input type="password" id="pw" name="pw" placeholder="비밀번호">
    <input type="submit" title="로그인" alt="로그인" value="로그인">
</form>  

네이버 로그인 스크립트

Perl에는 Andy Leste라는 개발자가 만든 WWW::Mechanize 라는 모듈이 따로 있어서 굉장히 쉽게 스크립트로 웹 브라우져를 사용하는 것처럼 굉장히 쉽게 웹에 접근하고 기능들을 사용할 수 있습니다. 파이썬에도 찾아보니 동일한 Mechanize 모듈이 있어서 사용하기로 결정했습니다.

import mechanize

browser = mechanize.Browser()  
browser.open("https://nid.naver.com/nidlogin.login")  
browser.select_form(nr=0)  
browser.form['id'] = "NAVER_ID"  
browser.form['pw'] = "NAVER_PW"  
browser.submit()  

정말 기본적인 내용들만 포함하여 작성해보았습니다. 하지만 이렇게 만든 스크립트를 실행해보면 2가지 문제가 발생합니다.

1. robots.txt

$ python naver_login.py

...
mechanize._response.httperror_seek_wrapper: HTTP Error 403: request disallowed by robots.txt  

이 스크립트를 실행하면 처음에는 실행조차 되지 않습니다. 네이버 로그인 사이트(?)의 robots.txt를 살펴보면 웹 크롤링을 허용하고 있지 않습니다.

$ curl http://nid.naver.com/robots.txt
User-agent: *  
Disallow: /  

하지만 우리는 무조건 로그인을 하는 것이 목표이기 때문에 robots.txt를 지키지 않고 그냥 크롤링하도록 하겠습니다. 위의 스크립트에 딱 한줄만 추가해주시면 정상적으로 데이터를 받아올 수 있습니다 :

browser.set_handle_robots(False)  

2. Cookie

위의 기본적인 스크립트로 로그인을 하고 네이버 서비스를 다시 열어보면 browser.open(URL)을 수행할 때 마다 새로운 세션으로 실행하는 것을 알 수 있습니다. 우리가 의도한 바는 로그인을 한번 하고 난 이후에는 그 세션을 유지해서 네이버 카페 출석수를 올리는 것이므로 받아온 쿠키를 저장하여 게속 사용할 예정입니다. 위의 스크립트에 아래의 내용을 추가해주시면 됩니다.

cj = mechanize.CookieJar()  
browser.set_cookiejar(cj)  

따라서 최종적으로는 아래와 같이 "네이버에 로그인을 하고, 쿠키를 저장해서 그 쿠키를 가지고 네이버 카페에 접속하는" 스크립트를 완성했습니다.

import mechanize

browser = mechanize.Browser()  
cj = mechanize.CookieJar()  
browser.set_cookiejar(cj)

browser.set_handle_robots(False)  
browser.open("https://nid.naver.com/nidlogin.login")  
browser.select_form(nr=0)  
browser.form['id'] = "NAVER_ID"  
browser.form['pw'] = "NAVER_PW"  
browser.submit()

brower.open("http://cafe.naver.com/NAVER_CAFE_NAME/")  

반복하기

사실 이 스크립트를 반복적으로 사용하는 방법은 여러가지가 있을 것 같습니다. 파이썬 스크립트도 그냥 짜는 방법도 있겠지만 ( crontab을 공부할 목적으로 ) Crontab을 사용해서 반복하기로 결정했습니다.

처음 목표는 안전하게 31분 간격으로 반복하는 것이였는데 도저히 31분이라는 애매한 수치를 crontab으로 반복하기 어려울 것 같아서 40분 간격으로 반복하도록 설정했습니다.

crontab -e 명령어를 통해서 수행할 명령어 리스트를 수정할 수 있습니다 :

0,40 */2 * * * /home/ubuntu/.pyenv/versions/VIRTUALENV_NAME/bin/python /home/ubuntu/naver_login.py  
20 1,3,5,7,11,13,15,17,19,21,23 * * * /home/ubuntu/.pyenv/versions/VIRTUALENV_NAME/bin/python /home/ubuntu/naver_login.py  

사실 40분 간격으로 하는 더 좋은 방법이 있는지는 잘 모르겠는데 딱히 생각나는 방법이 없어서, 짝수 시간대에는 0분과 40분에, 홀수 시간대에는 20분에 수행되도록 설정하였습니다. ( 예, 2시 0분 -> 2시 40분 -> 3시 20분 -> 4시 0분 ... )

로그를 확인해보면 정상적으로 동작함을 확인할 수 있습니다.

# /var/log/syslog

...
Sep 28 02:40:01 ip-172-31-14-250 CRON[29841]: (ubuntu) CMD (/home/ubuntu/.pyenv/versions/VIRTUALENV_NAME/bin/python /home/ubuntu/naver_login.py)  
...
Sep 28 03:20:01 ip-172-31-14-250 CRON[29875]: (ubuntu) CMD (/home/ubuntu/.pyenv/versions/VIRTUALENV_NAME/bin/python /home/ubuntu/naver_login.py)  
...
안수찬 @dobestan

안수찬 @dobestan

https://dobest.io/

소프트웨어 생태계에 기여할 수 있는 실용주의 프로그래머가 되고자 합니다. 나는 안수찬이다. 그러므로 나는 할 수 있다.

View Comments...