폼과 로그인 뚫기

Intro


이 포스트는 데이터 정리하기 - n-그램, 정규화 포스트에 의존합니다. 이전 포스트를 먼저 보시는걸 추천합니다.


제목이 상당히 파격적이다.

거창하게 뚫기 라는 단어를 사용했지만 사실 그저 로그인을 자동화하는 방법일 뿐이다.

웹에서는 로그인 해야만 얻을 수 있는 정보들이 많다. 우리가 지금껏 만든 스크레이퍼들은 HTTP GET 메소드를 써서 정보를 요청했다. 이번에는 웹 서버에서 저장하고 분석할 정보를 보내는 POST 메소드에 집중해보자.


기본적인 폼 전송


파이썬의 기본 라이브러리만으로도 웹 폼을 다룰수 있지만 비효율적 이다. 우리는 requests라는 라이브러리를 사용하자.

언제나처럼 설치는 pip

$ pip install requests

대표 사이트인 네이버부터 살펴보자.


_post-17-11-14-01
로그인 폼에서 마우스 우클릭에 검사를 눌러 페이지 소스를 확인해 보면,


_post-17-11-14-02
요런게 보인다.

입력필드의 변수 이름을 눈여겨 보자.

폼이 실제로 동작하는 곳은 숨겨져있다. 예를들면 login.php같은 페이지. 폼에 post요청을 보낼때는 폼이있는 그 페이지가 아닌 데이터를 처리하는 페이지에 보내야 한다.

requests라이브러리로 폼을 보내는건 단 4줄이면 가능하다.

import requests
params = {'id': '네이버 아이디', 'pw': '네이버 암호'}
r = requests.post("https://naver.com/login.php", data=params)
print(r.text)


안타깝지만 이 코드는 실행이 안된다.

대부분의 유명한 사이트는 robots.txt파일에서 로그인 폼에 접근하는 걸 거부하기 때문이다. 하지만 기본적인 페이지의 로그인과 보안이 높지않은 단순한 폼 상당부분에 적용할 수 있다.

단 2가지만 기억하면 된다.

  1. 데이터를 전송할 필드 이름.
  2. 폼 자체의 action속성, 즉 폼을 실제 처리하는 페이지.

라디오 버튼, 체크박스 …


물론 모든 웹 폼이 텍스트 필드와 전송 버튼만으로 구성되는 건 아니다. 라디오버튼, 체크박스, 셀렉트 박스, 슬라이더, 이메일, 날짜 등 에다가 자바 스크립트를 사용하면 쓸 수 있는 필드가 무한히 늘어난다. 무엇이든 개발자 마음대로 만들 수 있다.

이렇게 폼 필드가 다양하더라도 신경 쓸 것은 필드 이름과 값 두가지다.

POST 폼이 너무 복잡해서 막혀있고 브라우저가 정확히 어떤 매개변수를 서버에 보내는지 알고싶다면, 브라우저의 개발자 도구를 보는게 좋다.
_post-17-11-14-03
크롬 개발자도구로 네이버 페이지를 보면 대충 이렇게 생겼다.


로그인과 쿠키 처리


최신 웹사이트는 대부분 쿠키를 사용해서 누가 로그인했고 누가 안 했는지 추적한다. 일단 사용자가 로그인 요청을 인증하면, 사이트는 당신의 브라우저에 쿠키를 저장한다. 이런 쿠키에는 보통 서버에서 생산된 토큰, 만료일, 트래킹 정보가 들어있다.

사이트는 나중에 이 쿠키를 당신이 그 사이트에 머물며 방문하는 각 페이지에서 일종의 인증 증거로 사용한다.

쿠키에 관한 예제는 책에있는 예제를 활용했다.

여기 사이트에 단순한 로그인 폼이 있다. 사용자 이름은 아무거나 써도 되지만, 비밀번호는 반드시 password 여야 한다.

이 폼을 처리하는 페이지는 ‘http://pythonscraping.com/pages/cookies/welcom.php’이고, 이페이지에는 ‘메인 사이트’ 페이지인 ‘http://pythonscraping.com/pages/cookies/profile.php’를 가리키는 링크가 있다.

로그인하지 않고 환영 페이지나 프로필 페이지에 접근하려 하면 에러 메시지와 함께 먼저 로그인하라는 안내가 표시된다. 프로필 페이지에서는 로그인 페이지에서 브라우저 쿠키를 만들었는지 체크한다.

requests라이브러리를 사용하면 쿠키 추적도 쉽다.

import requests
session = requests.Session()
params = {'username':'username', 'password':'password'}
s = session.post("http://pythonscraping.com/pagse/cookies/welcom.php", params)
print("Cookie is set to:")
print(s.cookies.get_dict())
print("-------------")
print("Going to profile page...")
s = session.get("http://pythonscraping.com/pages/cookies/profile.php")
print(s.text)


이 코드는 로그인 폼을 처리하는 환영 페이지에 로그인 매개변수를 보내고 마지막 요청 결과에서 쿠키를 가져와 출력으로 확인한다. 그런뒤에 session매개변수를 통해 그 쿠키를 프로필 페이지에 보낸다.


기타 폼 문제


웹 폼은 온갖 악의적 봇들이 들끓는 장소다. 봇이 사용자 계정을 만들고 서버 자원을 낭비하고, 블로그에 스팸을 뿌려대길 원하는 사람은 아무도없다.

이런 봇들을 차단하기위해 HTML 폼에는 즉시 드러나지 않은 보안 기능이 포함될 때가 많다.

자동 가입 방지 문자(captcha), 이미치 처리와 텍스트 인식에 관해서는 나중에 알아보자.

이상한 에러를 만나거나, 서버가 알 수 없는 이유로 당신의 크롤러를 차단한다면 허니팟과 숨겨진 필드, 다른 보안수단이 동원되었을 가능성이 높다.


다음포스트 - 셀레니움 사용법