Wysyłanie formularza POSTem za pomocą biblioteki requests

0

Witam,
Uczę się od jakiegoś czasu pythona, poszerzając wiedzę trafiłem na bibliotekę requests. Chcę wysłać parametrem post jakieś dane. Do testu biblioteki wykorzystałem odzyskiwanie profilu na facebooku. Skrypt wysyła POSTem mój adres e-mail i powinien mi wyświetlić mój profil, jednak po wysłaniu POSTa ciągle siedzi na stronie wyjściowej.

Składniowo raczej wszystko jest ok, bo nie ma żadnego błędu!!

import requests
get_response = requests.get(url='https://www.facebook.com/login/identify?
ctx=recover')
post_data = {'email':'mycorrectemailaddress'}
post_response = requests.post(url="https://www.facebook.com/login/identify?ctx=recover/POST", data=post_data)
print(post_response.text)
0
  1. Gdzie podajesz swoje hasło?
  2. Nie wysyłasz pełnej formy, wymaganej przez facebooka
  3. Lepiej będzie jak użyjesz selenium lub mechanize
0
  1. Ja się nie loguje do facebooka
  2. Patrz wyżej

Z selenium właśnie bym wiedział jak to zrobić, ale nie chcę, żeby przeglądarka brała w tym udział. Chodzi mi generalnie o to, żeby znaleźć odpowiedni input na stronie i wysłać tam email, po czym zyskać odpowiedni wynik. W tym przypadku chodzi mi o odzyskiwanie konta na facebooku. Robię skrypt, który, że tak powiem szuka ludzi. Po wpisaniu maila w formularz chcę uzyskać imię i nazwisko profilu.
Na stronie https://www.facebook.com/login/identify?ctx=recover mamy 3 miejsca gdzie możemy wpisać jakiś tekst.

Login

<input type="email" class="inputtext" name="email" id="email" value="" tabindex="1">

Hasło

<input type="password" class="inputtext" name="pass" id="pass" tabindex="2">

I ten, który mnie najbardziej interesuje, czyli:

<input type="text" class="inputtext" id="identify_email" name="email" autofocus="1">

W niego chcę wpisać odpowiedniego maila i uzyskać odpowiedni wynik. I tu moje pytanie jak to zrobić bez Webdrivera. BeautifulSoup ?

0
import requests

urlbas = "http://m.facebook.com/login/identify?ctx=recover"

headers = {
    "Host": "m.facebook.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv51.0) Gecko/20100101 Firefox/51.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US;q=0.7,en;q=0.3",
    "Accept-Encoding":	"gzip, deflate, br"
}

payload={
    #"lsd": "-------",
    "email": "email",
    #"did_submit": "Search"
}

def print_url(r, *args, **kwargs):
    print(r.url)

with requests.Session() as req:
    req.encoding = "utf-8"
    req = requests.post(urlbas, data=payload, headers=headers, hooks=dict(response=print_url))

Jeśli się powiedzie to

print_url

da ci trzy rezultaty, drugi będzie odnośnikiem do dalszej części formularza.

0

@iM32

Ad. 1 Sorry za przysłowiowe męczenie buły, ale do tej pory miałem tylko docznienia z automatyzacją za pomocą Webdrivera i chciałem pójść krok dalej. W Webdriverze wszystko jest o wiele prostsze, wystarczy zlokalizować element po ID czy xpathem, wpisać tekst do formularza, wysłać i znowu po lokalizacji danego elementu wyciągnąć interesujące mnie dane z jakiegoś tagu html. Skrypt, które chce napisać miałby może z 10 linijek kodu. Tutaj jest trochę więcej roboty i do tego dochodzi zapoznanie się z biblioteką requests. Mógł byś dodać komentarze do kodu? Co się mniej więcej dzieje w danym momencie? Nie rozumiem czemu to nie może wyglądać jakoś tak:

import requests
headers = {'User-Agent': 'Mozilla/5.0'}
payload = {'email':'mójemail'}

session = requests.Session()
x = session.post('http://m.facebook.com/login/identify?ctx=recover',headers=headers,data=payload)
print x.text

Czemu w kodzie powyżej po wysłaniu POST skrypt zwraca mi htmla ze strony wyjściowej?

AD.2 Kawałek Twojego kodu, którego już za bardzo nie rozumiem.

def print_url(r, *args, **kwargs): #Poczytałem trochę o *args i **kwargs, ale nie do końca to rozumiem, tym bardziej, że kod działa bez *args
    print(r.url)
    # z = requests.get(r.url) Dodałem te dwie linijki, żeby zescrapować kod html interesującej mnie strony, ale nie działa tak jak bym sobie tego życzył :)
    # print z.text
 
#Tutaj to już totalnie nie wiem o co chodzi, byłbym wdzięczny jak byś to mniej więcej opisał, chodzi mi głównie o with
with requests.Session() as req: 
    req.encoding = "utf-8" 
    req = requests.post(urlbas, data=payload, headers=headers, hooks=dict(response=print_url))

Nie wiem czy mój brak zrozumienia wynika z niedoboru wiadomości na temat protokołu http i metody POST czy samego Pythona. Będę wdzięczny za kilka komentarzy do kodu. Dziękuje pięknie za pomoc.

1

Czemu w kodzie powyżej po wysłaniu POST skrypt zwraca mi htmla ze strony wyjściowej?

Ponieważ .text zwraca zawartość strony, .content zwrócił by ci ją w formie bajtów(przydatne kiedy chcesz pobrać obrazek, lub inny binarny format).

*args, **kwargs zwracają dodatkowe rzeczy takie jak np. timeout.

O requests.Session() i req.encoding musisz poczytać w dokumentacji, bo to podstawy.

r.url zwraca każy ciąg jako string ale w dość specyficznej formie, bo z lekkim opóźnieniem i średnio da się coś tym zrobić(przynajmniej z moją wiedzą...)
Może ktoś bardziej obeznany będzie ci w stanie pomóc @Shalom @nalik @Patryk27 @lion137 @Althorion

0

@iM32
Kurde no nie wierzę, że wysłanie formularza POSTem sprawia aż tyle problemów. Ja po prostu chcę przejść do kolejnej strony po wysłaniu zapytania...

with requests.Session() as req: <-- Nie wyjaśniłeś dalej tego czego nie wiem, czyli co to jest with? To działa jak for?

1

@learnpython no ale to nie jest taki ot formularz z d**y jednak. To co robisz nie zadziała z wielu powodów, takich jak choćby CSRF. Moja rada: wykonaj ten request ręcznie z włączoną zakładką "network" w narzędziach developerskich/firebugu i zobacz jak dokładnie wygląda request wysyłany przez przeglądarkę. Dodatkowo facebook może jakoś po stronie clienta coś mieszać javascriptem, bo i czemu nie?

0

@Shalom

Takie coś jeszcze wyskubałem. Dzięki za odpowiedź.

import requests
from BeautifulSoup import BeautifulSoup
Soup = BeautifulSoup
headers = {'User-Agent': 'Mozilla/5.0'}
payload={
    "lsd": "AVqS_aom",
    "email": "mojemail",
    "did_submit": "Szukaj"
}

session = requests.Session()
x = session.post('http://m.facebook.com/login/identify?ctx=recover', headers=headers, data=payload)
#print x.content
x.encoding = "utf-8"
parsed = BeautifulSoup(x.content)
print(parsed)

Jeszcze wytrzasnąłem taki link po użyciu live http headers, ale nie działa po wpisaniu go w przeglądarke:

https://m.facebook.com/login/identify?lsd=AVqS_aom&email=email&did_submit=Szukaj

POST wysyłany na stronę to:
lsd=AVqS_aom&email=email&did_submit=Szukaj

Ktoś wie co oznacza lsd=?

Z resztą skoro @iM32 wykombinował z tego linka do profilu, to na pewno da się to jakoś wykorzystać i zescrapować.

1 użytkowników online, w tym zalogowanych: 0, gości: 1