Como “logar” em um site usando o módulo Requests do Python?

95

Estou tentando postar uma solicitação para fazer login em um site usando o módulo Requests em Python, mas realmente não está funcionando. Sou novo nisso ... então não consigo descobrir se devo criar meus cookies de nome de usuário e senha ou algum tipo de autorização de HTTP que encontrei (??).

from pyquery import PyQuery
import requests

url = 'http://www.locationary.com/home/index2.jsp'

Agora, acho que devo usar "post" e cookies ....

ck = {'inUserName': 'USERNAME/EMAIL', 'inUserPass': 'PASSWORD'}

r = requests.post(url, cookies=ck)

content = r.text

q = PyQuery(content)

title = q("title").text()

print title

Tenho a sensação de que estou fazendo a coisa dos cookies errada ... não sei.

Se não fizer login corretamente, o título da página inicial deve ser "Locationary.com" e, se for, deve ser "Página inicial".

Se você pudesse explicar algumas coisas sobre pedidos e cookies para mim e me ajudar com isso, eu agradeceria muito. : D

Obrigado.

... Ainda não funcionou realmente. Ok ... então isso é o que o HTML da página inicial diz antes de você fazer login:

</td><td><img src="http://www.locationary.com/img/LocationaryImgs/icons/txt_email.gif">    </td>
<td><input class="Data_Entry_Field_Login" type="text" name="inUserName" id="inUserName"  size="25"></td>
<td><img src="http://www.locationary.com/img/LocationaryImgs/icons/txt_password.gif"> </td>
<td><input  class="Data_Entry_Field_Login"  type="password" name="inUserPass"     id="inUserPass"></td>

Acho que estou fazendo certo, mas o resultado ainda é "Locationary.com"

2ª EDIT:

Quero poder permanecer conectado por muito tempo e sempre que solicitar uma página nesse domínio, quero que o conteúdo apareça como se eu estivesse conectado.

Marcus Johnson
fonte

Respostas:

44

Se as informações que você deseja estão na página para a qual você é direcionado imediatamente após o login ...

Vamos chamar sua ckvariável em payloadvez disso, como nos documentos de solicitações de python :

payload = {'inUserName': 'USERNAME/EMAIL', 'inUserPass': 'PASSWORD'}
url = 'http://www.locationary.com/home/index2.jsp'
requests.post(url, data=payload)

De outra forma...

Consulte https://stackoverflow.com/a/17633072/111362 abaixo.

Katy Lavallee
fonte
Eu fiz funcionar de uma maneira diferente usando urllib, urrlib2 e cookielib e alguns cabeçalhos HTTP.
Marcus Johnson
23
Infelizmente, não posso excluir isso porque é a resposta aceita. Acho que não entendi a pergunta quando postei isso (foi esclarecido depois), então não sei por que foi aceito. Minha resposta só funciona se os dados de que você precisa estiverem na página para a qual você é redirecionado após o login. @tigerFinch tem uma resposta muito melhor.
Katy Lavallee de
228

Sei que você encontrou outra solução, mas para quem como eu encontra essa dúvida, procurando a mesma coisa, ela pode ser conseguida com as seguintes solicitações:

Em primeiro lugar, como fez Marcus, verifique a origem do formulário de login para obter três informações - a url para a qual o formulário envia e os atributos de nome dos campos de nome de usuário e senha. Em seu exemplo, eles são inUserName e inUserPass.

Depois de fazer isso, você pode usar uma requests.Session()instância para fazer uma solicitação de postagem para o url de login com seus detalhes de login como uma carga útil. Fazer solicitações de uma instância de sessão é essencialmente o mesmo que usar solicitações normalmente; simplesmente adiciona persistência, permitindo que você armazene e use cookies etc.

Supondo que sua tentativa de login foi bem-sucedida, você pode simplesmente usar a instância da sessão para fazer outras solicitações ao site. O cookie que o identifica será usado para autorizar as solicitações.

Exemplo

import requests

# Fill in your details here to be posted to the login form.
payload = {
    'inUserName': 'username',
    'inUserPass': 'password'
}

# Use 'with' to ensure the session context is closed after use.
with requests.Session() as s:
    p = s.post('LOGIN_URL', data=payload)
    # print the html returned or something more intelligent to see if it's a successful login page.
    print p.text

    # An authorised request.
    r = s.get('A protected web page url')
    print r.text
        # etc...
tigerFinch
fonte
12
A questão, entretanto, é como obter o formulário de login do POST? Como posso saber se ele se chama inUserName em vez de username, USERNAME etc?
lsheng
4
@Twinkle olhe o código-fonte HTML do formulário para ver como são chamados nele.
Aaron Schumacher
3
s.text parece não funcionar, mas ainda estou dando a você um amor de voto por me mostrar isso adorável com solicitações ... sintaxe
Software Prophets
s.text não funciona porque deveria ser algo assim: p = s.post('LOGIN_URL.....e entãop.text
Sebastian
2
@HalcyonAbrahamRamirez Não acho que este seja o lugar certo para você procurar ajuda. Sugiro ler perguntas sobre seu desafio especificamente como: stackoverflow.com/questions/21928368/… e se você não conseguir resolvê-lo, abra sua própria pergunta.
Sebastian
36

Deixe-me tentar simplificar, suponha que o URL do site seja http://example.com/ e suponha que você precise se inscrever preenchendo o nome de usuário e a senha, então vamos para a página de login dizer http: // example. com / login.php agora e veja o seu código-fonte e pesquise o URL de ação que estará na tag de formulário algo como

 <form name="loginform" method="post" action="userinfo.php">

agora pegue userinfo.php para fazer um URL absoluto que será ' http://example.com/userinfo.php ', agora execute um script python simples

import requests
url = 'http://example.com/userinfo.php'
values = {'username': 'user',
          'password': 'pass'}

r = requests.post(url, data=values)
print r.content

Espero que algum dia isso ajude alguém em algum lugar.

Tarun Venugopal Nair
fonte
1
bom - note que às vezes inspecionar o elemento do campo nome / senha pode revelar o arquivo chamado em vez do botão (o meu acabou de dizer 'ação' na inspeção do botão, o url foi mostrado na inspeção dos campos usr / pass)
baxx
2
Se você estiver usando o Chrome, abra o devtools na guia de rede e depois de fazer a solicitação, você pode inspecionar os valores reais, com quais chaves e para onde foram enviados, isso é útil para formulários que não usam a mecânica tradicional e, em vez disso, use javascript / ajax para processar o formulário.
Roberto Arosemena
1
neste caso, alguma ideia de como fazer a página pop up direto em vez de imprimir o conteúdo da página?
Você precisará usar o webbrowsermódulo
R. Barrett
Além disso, o texto acima print r.contentestá errado, ele deveria estar usandoprint(r.content)
R. Barrett
6

Descubra o nome das entradas usadas no formulário dos sites para nomes de usuários <...name=username.../>e senhas <...name=password../>e substitua-os no script abaixo. Substitua também o URL para apontar para o site desejado para fazer login.

login.py

#!/usr/bin/env python

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
payload = { 'username': '[email protected]', 'password': 'blahblahsecretpassw0rd' }
url = 'https://website.com/login.html'
requests.post(url, data=payload, verify=False)

O uso de disable_warnings(InsecureRequestWarning)silenciará qualquer saída do script ao tentar fazer login em sites com certificados SSL não verificados.

Extra:

Para executar este script a partir da linha de comando em um sistema baseado em UNIX, coloque-o em um diretório, ou seja, home/scriptsadicione este diretório ao seu caminho ~/.bash_profileou a um arquivo semelhante usado pelo terminal.

# Custom scripts
export CUSTOM_SCRIPTS=home/scripts
export PATH=$CUSTOM_SCRIPTS:$PATH

Em seguida, crie um link para este script python dentro home/scripts/login.py

ln -s ~/home/scripts/login.py ~/home/scripts/login

Feche seu terminal, inicie um novo, execute login

David Morton
fonte
4

A requests.Session()solução ajudou no login em um formulário com CSRF Protection (conforme usado nos formulários Flask-WTF). Verifique se um csrf_tokené obrigatório como um campo oculto e adicione-o à carga com o nome de usuário e a senha:

import requests
from bs4 import BeautifulSoup

payload = {
    'email': '[email protected]',
    'password': 'passw0rd'
}     

with requests.Session() as sess:
    res = sess.get(server_name + '/signin')
    signin = BeautifulSoup(res._content, 'html.parser')
    payload['csrf_token'] = signin.find('input', id='csrf_token')['value']
    res = sess.post(server_name + '/auth/login', data=payload)
Naamã
fonte