#python #python-requests
#python #python-запросы
Вопрос:
Я пишу скрипт для автоматического извлечения PDF-файлов со страницы моего университета в Moodle. PDF-файлы доступны только после входа в систему. Я использую requests
(with requests.session
) для заполнения формы входа и отправки своих учетных данных для создания cookie, чтобы я мог получить доступ к файлам.
Проблема в том, что форма входа не просто принимает мое имя пользователя и пароль, но также принимает кучу странных переменных, генерируемых при загрузке страницы входа, включая уникальный токен (все они невидимы для пользователя). Теперь я успешно вошел в систему с python, извлекая эти переменные с помощью beautiful soup и добавляя их в полезную нагрузку при публикации формы входа, вот так:
username = input("Username: ")
password = input("Password: ")
moodleLoginURL = "https://auth.bath.ac.uk/login"
s = requests.Session()
r = s.get(moodleLoginURL)
soup = bs4.BeautifulSoup(r.text, "html.parser")
token = soup.find('input', {'name' : 'execution'}).get('value')
lt = soup.find('input', {'name' : 'lt'}).get('value')
_eventId = soup.find('input', {'name' : '_eventId'}).get('value')
submit = soup.find('input', {'name' : 'submit'}).get('value')
payload = {"username" : username, "password" : password, "execution" : token, "lt" : lt, "_eventId" : _eventId, "submit" : submit}
s.post(moodleLoginURL, data = payload)
Это работает, но моя проблема в том, что это не будет работать с другими веб-сайтами и не устойчиво к обновлениям со стороны менеджеров веб-сайтов. Мой вопрос в том, есть ли способ автоматически собирать данные, сгенерированные за кулисами (то есть все данные, подлежащие публикации, за исключением данных пользовательского ввода), вместо того, чтобы вручную извлекать каждую переменную, специфичную для данного веб-сайта? Таким образом, я мог бы войти на любой веб-сайт, который автоматически генерирует токены и т.д., возможно, с небольшими изменениями, необходимыми для переменных имени пользователя и пароля. Возможно ли это?
(Если вы хотите посмотреть HTML для формы входа, сайт, на который я пытаюсь войти, находится здесь: https://auth.bath.ac.uk/login)
Ответ №1:
Обычно все дополнительные переменные являются input
тегами и имеют type=hidden
атрибут. Итак, вы можете сделать что-то вроде этого —
payload = {}
for hidden_input_elem in soup.findAll('input', {'type' : 'hidden'}):
payload[hidden_input_elem.get('name')] = hidden_input_elem.get('value')
и после этого добавьте другие переменные пользовательского ввода в payload dict.
-Редактировать: исправлена функция ‘findAll’ с заглавной буквы