Почему не работает скрипт входа в систему Requests и BeautifulSoup? - PullRequest
0 голосов
/ 21 апреля 2020

Ниже приведен фрагмент кода, который я создал на обороте библиотек Requests и BeautifulSoup для Python 3.

import requests as rq
from bs4 import BeautifulSoup as bs

def get_data():
    return {'email': str(input('Enter your email.')),
        'password': str(input('Enter your password.'))}

def obtain_data():
    login_data=get_data()
    form_data={'csrf_token': login_data['email'],
               'login': '1',
               'redirect': 'account/dashboard',
               'query': None,
               'required': 'email,password',
               'email': login_data['email'],
               'password': login_data['password']}
    headers={'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}
    with rq.Session() as s:
        r=s.get('https://www.formstack.com/admin/user/login',headers=headers)
        form_data['csrf_token']+=','+bs(r.content, 'html.parser').find('input',attrs={'name':'csrf_token'})['value']
        r=s.post('https://www.formstack.com/admin/user/login',data=form_data,headers=headers)
        assert('Collect' in bs(r.content,'html.parser'))

obtain_data()

Цель кода - войти в систему. Опросная платформа называется Formstack с использованием учетных данных, полученных с помощью get_data(). Для этого мы создаем сеанс с использованием запросов. Отсюда мы отправляем запрос get на страницу входа в Formstack. Мы собираем дерево разбора ответа на этот запрос, используя BeautifulSoup, и, следовательно, получаем значение входного тега HTML с помощью name='csrf_token' (опять же, используя BeautifulSoup), поскольку нам нужно это значение для заполнения формы входа в систему. Отсюда мы собираем форму, обозначенную form_data в приведенном выше коде, и отправляем запрос на публикацию с помощью этой формы, снова на страницу входа в Formstack. должен войти в мою учетную запись Formstack, но по какой-то причине этого не происходит. Я проверил, что это не так, запустив строку assert() на содержимом первой страницы, которую я вижу после входа в систему, и, используя этот метод, я всегда получаю ошибку подтверждения.

Я не очень хорошо знаком с веб-скребком в Python, и, следовательно, я не уверен, где go с этой проблемой. Я пытался разрешить перенаправления как в запросе get, так и в запросе post, но в обоих случаях я потерпел неудачу. Спасибо за любую помощь, спасибо.

1 Ответ

1 голос
/ 21 апреля 2020

Вам нужно будет имитировать c поведение браузера, как если бы запрос был сделан из браузера. Иногда это также требовало заголовков, но здесь они, кажется, не нужны (вы все равно можете добавить их, если хотите).

Глядя на вкладку «Сеть» моего браузера с включенным «Сохранять», я вижу порядок, в котором выполняются запросы. Важной частью является запрос GET, который выполняется до фактического запроса POST (который отправляет ваши учетные данные). Порядок здесь важен, поэтому он сохранен.

Примечание 1. Я использовал здесь регулярное выражение для извлечения токена, но вы должны использовать BeautifulSoup, если вам нужно проанализировать страницу в другой раз.

Примечание 2: Кажется, что страница загружается с течением времени, когда JavaScript получает данные из динамического c бэкэнда. Обязательно проверьте вкладку «Сеть» и посмотрите, какие запросы выполняются, чтобы получить то, что вам нужно, и сделайте те же запросы в своем коде.

import requests
import re
email = "email"
password = "pwd"
with requests.Session() as sess:
    login_page = sess.get("https://www.formstack.com/admin/user/login")
    #extract token from page source, you can use any other method for this
    token = re.search(r'token="(.*?)"', login_page.text).group(1)
    #the exact format as seen in the "Networks" tab of the browser
    data = {
    "csrf_token": token,
    "login": "1",
    "redirect": "account/dashboard",
    "query": "",
    "required": "email,password",
    "email": email,
    "password": password
    }
    GET_url = "https://www.formstack.com/admin/platform-sso/determineSsoStatus/" + email
    POST_url = "https://www.formstack.com/admin/session/create"
    #keep the order of requests as seen in the browser's Network tab
    sess.get(GET_url)
    final = sess.post(POST_url, data=data)
    #check final redirect, and see if user is taken to the dashboard or redirected back to login
    #uncomment to see where the redirects end at:
    #print(final.url)
    if "redirect" in final.url:
        print("Incorrect creds")
    else:
        print("Success")
...