Jak „zalogować się” do serwisu WWW za pomocą modułu Requests w Pythonie?

98

Próbuję wysłać prośbę o zalogowanie się do witryny internetowej za pomocą modułu Requests w Pythonie, ale tak naprawdę nie działa. Jestem nowy w tym ... więc nie mogę dowiedzieć się, czy powinienem utworzyć pliki cookie dotyczące nazwy użytkownika i hasła lub jakiś rodzaj autoryzacji HTTP, który znalazłem (??).

from pyquery import PyQuery
import requests

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

Więc teraz myślę, że powinienem używać „post” i plików cookie…

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

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

content = r.text

q = PyQuery(content)

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

print title

Mam wrażenie, że robię ciasteczka źle ... Nie wiem.

Jeśli nie loguje się poprawnie, tytuł strony głównej powinien wskazywać „Locationary.com”, a jeśli tak, powinien to być „Strona główna”.

Gdybyś mógł wyjaśnić mi kilka rzeczy na temat próśb i plików cookie i pomóc mi w tym, byłbym bardzo wdzięczny. :RE

Dzięki.

… To nadal nie działa. OK ... więc tak mówi kod HTML strony głównej przed zalogowaniem:

</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>

Myślę więc, że robię to dobrze, ale wynik nadal to „Locationary.com”

2. EDYCJA:

Chcę być zalogowany przez długi czas, a za każdym razem, gdy żądam strony w tej domenie, chcę, aby zawartość wyświetlała się tak, jakbym był zalogowany.

Marcus Johnson
źródło

Odpowiedzi:

44

Jeśli żądane informacje znajdują się na stronie, do której jesteś przekierowywany zaraz po zalogowaniu ...

Zamiast tego wywołajmy twoją ckzmienną payload, jak w dokumentach python-request :

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

Inaczej...

Zobacz https://stackoverflow.com/a/17633072/111362 poniżej.

katy lavallee
źródło
Mam to do pracy w inny sposób, używając urllib, urrlib2 i cookielib oraz niektórych nagłówków HTTP.
Marcus Johnson,
23
Niestety nie mogę tego usunąć, ponieważ jest to zaakceptowana odpowiedź. Myślę, że nie zrozumiałem pytania, kiedy to opublikowałem (zostało wyjaśnione później), więc nie jestem pewien, dlaczego zostało zaakceptowane. Moja odpowiedź działa tylko wtedy, gdy potrzebne dane znajdują się na stronie, na którą zostaniesz przekierowany po zalogowaniu. @tigerFinch ma znacznie lepszą odpowiedź.
katy lavallee
230

Wiem, że znalazłeś inne rozwiązanie, ale dla takich jak ja, którzy znajdują to pytanie i szukają tego samego, można to osiągnąć za pomocą następujących żądań:

Po pierwsze, podobnie jak Marcus, sprawdź źródło formularza logowania, aby uzyskać trzy informacje - adres URL, na który formularz wysyła, oraz atrybuty nazwy w polach nazwy użytkownika i hasła. W jego przykładzie są to inUserName i inUserPass.

Gdy już to zrobisz, możesz użyć requests.Session()instancji, aby wysłać żądanie wpisu do adresu URL logowania z danymi logowania jako ładunkiem. Wykonywanie żądań z instancji sesji jest zasadniczo takie samo, jak normalne korzystanie z żądań, po prostu dodaje trwałości, umożliwiając przechowywanie i używanie plików cookie itp.

Zakładając, że próba logowania się powiodła, możesz po prostu użyć instancji sesji, aby wysłać dalsze żądania do witryny. Plik cookie, który Cię identyfikuje, będzie używany do autoryzacji żądań.

Przykład

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
źródło
13
Pytanie jednak, jak uzyskać formularz logowania POST? Skąd mam wiedzieć, czy nazywa się to inUserName, a nie nazwa użytkownika, NAZWA UŻYTKOWNIKA itp.?
lsheng
4
@ Twinkle spójrz na źródło HTML formularza, aby zobaczyć, jak się tam nazywają.
Aaron Schumacher
3
s.text wydaje się nie działać, ale nadal daję wam trochę miłości do głosowania za pokazanie mi tego cudownego z żądaniami ... składnia
Software Prophets
s.text nie działa, bo powinno być mniej więcej tak: p = s.post('LOGIN_URL.....a potemp.text
Sebastian
2
@HalcyonAbrahamRamirez Myślę, że to nie jest właściwe miejsce, aby szukać pomocy. Proponuję przeczytać pytanie dotyczące twojego wyzwania, takie jak: stackoverflow.com/questions/21928368/ ... a jeśli nie możesz go rozwiązać, otwórz własne pytanie.
Sebastian
36

Spróbuję to uprościć, załóżmy, że adres URL witryny to http://example.com/ i załóżmy, że musisz zarejestrować się, wypełniając nazwę użytkownika i hasło, więc przechodzimy do strony logowania, mówiąc http: // przykład. com / login.php teraz i wyświetl jego kod źródłowy i wyszukaj adres URL akcji, który będzie w formie tagu podobnego do

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

teraz weź userinfo.php, aby utworzyć bezwzględny adres URL, który będzie „ http://example.com/userinfo.php ”, teraz uruchom prosty skrypt Pythona

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

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

Mam nadzieję, że to kiedyś komuś pomoże.

Tarun Venugopal Nair
źródło
1
fajny - zauważ, że czasami inspekcja elementu pola name / pass może ujawnić wywołany plik, a nie przycisk (mój właśnie powiedział
``
2
Jeśli używasz chrome, otwórz devtools na karcie sieci i po złożeniu żądania możesz sprawdzić rzeczywiste wartości, z jakimi kluczami i gdzie zostały wysłane, jest to przydatne w przypadku formularzy, które nie używają tradycyjnej mechaniki, a zamiast tego użyj javascript / ajax do przetwarzania formularza.
Roberto Arosemena
1
w takim przypadku masz jakiś pomysł, jak sprawić, by strona internetowa pojawiała się bezpośrednio, zamiast drukować zawartość strony?
Będziesz musiał użyć webbrowsermodułu
R. Barrett
Również jego powyższe print r.contentjest złe, którego powinien używaćprint(r.content)
R. Barrett
6

Znajdź nazwy danych wejściowych używanych w formularzu witryn internetowych dla nazw użytkowników <...name=username.../>i haseł <...name=password../>i zamień je w poniższym skrypcie. Zastąp także adres URL, aby wskazywał żądaną witrynę, do której chcesz się zalogować.

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)

Użycie disable_warnings(InsecureRequestWarning)spowoduje wyciszenie wszelkich danych wyjściowych skryptu podczas próby zalogowania się do witryn z niezweryfikowanymi certyfikatami SSL.

Dodatkowy:

Aby uruchomić ten skrypt z wiersza poleceń w systemie opartym na systemie UNIX, umieść go w katalogu, tj. home/scriptsDodaj ten katalog do swojej ścieżki w ~/.bash_profilelub podobnego pliku używanego przez terminal.

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

Następnie utwórz link do tego skryptu Pythona w środku home/scripts/login.py

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

Zamknij terminal, uruchom nowy, biegnij login

David Morton
źródło
4

requests.Session()Roztwór wspomagany rejestrowanie w postaci o ochronie CSRF (które są stosowane w postaci skrzynkowego WTF). Sprawdź, czy pole csrf_tokenjest wymagane jako ukryte i dodaj je do ładunku za pomocą nazwy użytkownika i hasła:

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)
naaman
źródło