Как заполнить форму JavaScript с помощью Python?

#selenium #web-scraping #beautifulsoup #scrapy #mechanize

#selenium #очистка веб-страниц #beautifulsoup #scrapy #механизировать

Вопрос:

Я хочу использовать Python для заполнения этой формы.

Я пытался использовать Mechanize, но это форма Microsoft, которая использует JavaScript и не имеет тега form и URL-адреса GET / POST. Возможно, BeautifulSoup / Selenium может это сделать, но у меня нет никакого опыта в очистке JS-форм. Кто-нибудь может мне помочь и подсказать, как это сделать?

Вот что я пробовал, Mechanize не может распознать какую-либо форму на странице:

 import mechanize

def main():
    br = mechanize.Browser()
    br.set_handle_robots(False)
    br.set_handle_refresh(False)
    br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]
    response  = br.open("https://forms.office.com/Pages/ResponsePage.aspx?id=8Pm7rtoj40mYvzIXGrvJvCxQDveyljlCrKN2Teo3EHFUQVNaWDlYRkhYR09JRTZWRFpKTTNIQU9HUC4u")
    for form in br.forms():
        print("Form name:", form.name) #prints nothing
        print(form) #prints nothing

if __name__ == '__main__':
    main()
  

Комментарии:

1. Ваши испытания кода?

Ответ №1:

Selenium работает нормально.

Вам нужно будет установить компоненты

  • установите selenium pip install selenium
  • Вам необходимо убедиться, что вы загрузили правильный chromedriver (или другой драйвер) для вашего браузера и версий ОС и добавьте его в path

Затем выполняется:

 from selenium import webdriver

driver = webdriver.Chrome()
url = "https://forms.office.com/Pages/ResponsePage.aspx?id=8Pm7rtoj40mYvzIXGrvJvCxQDveyljlCrKN2Teo3EHFUQVNaWDlYRkhYR09JRTZWRFpKTTNIQU9HUC4u"
driver.get(url)


name = driver.find_element_by_xpath("//div[@class='question-title-box'][.//span[text()='NAME']]/following-sibling::*//input")
name.send_keys("hello, World")

setionSelection = "F"
section = driver.find_element_by_xpath("//div[@class='question-title-box'][.//span[text()='Section']]/following-sibling::*//input[@value='"   setionSelection   "']")
section.click()

date = driver.find_element_by_xpath("//input[contains(@placeholder, 'Please input date')]")
date.send_keys("01/12/2020")


submit = driver.find_element_by_xpath("//div[text()='Submit']")
submit.click()
  

xapths немного длинноваты, но они основаны на тексте вопроса, поэтому потенциально стабильны

Рабочий selenium


Альтернативный подход — Когда вы говорите, что URL-адреса POST нет, вы проверяли devtools? — Это раскрывает назначение формы:

 Request URL: https://forms.office.com/formapi/api/aebbf9f0-23da-49e3-98bf-32171abbc9bc/users/f70e502c-96b2-4239-aca3-764dea371071/forms('8Pm7rtoj40mYvzIXGrvJvCxQDveyljlCrKN2Teo3EHFUQVNaWDlYRkhYR09JRTZWRFpKTTNIQU9HUC4u')/responses
Request Method: POST
  

он также предоставляет полезную нагрузку… Это первая отправка:

 {startDate: "2020-08-17T10:40:18.504Z", submitDate: "2020-08-17T10:40:18.507Z",…}
answers: "[{"questionId":"r8f09d63e6f6f42feb2f8f4f8ed3f9389","answer1":"Hello, World"},{"questionId":"r28fe12073dfa47399f8ce95ae679dccf","answer1":"G"},{"questionId":"r8f9e9fedcc2e410c80bfa1e0e3ef9750","answer1":"2020-08-28"}]"
startDate: "2020-08-17T10:40:18.504Z"
submitDate: "2020-08-17T10:40:18.507Z"
  

Эти идентификаторы вопросов UUID / GUIDS URL post, похоже, подходят для этой формы. Каждый раз, когда я запускаю форму, они не обмениваются. Это второй запуск:

 {startDate: "2020-08-17T10:43:48.544Z", submitDate: "2020-08-17T10:43:48.546Z",…}
answers: "[{"questionId":"r8f09d63e6f6f42feb2f8f4f8ed3f9389","answer1":"test me"},{"questionId":"r28fe12073dfa47399f8ce95ae679dccf","answer1":"G"},{"questionId":"r8f9e9fedcc2e410c80bfa1e0e3ef9750","answer1":"2020-08-12"}]"
startDate: "2020-08-17T10:43:48.544Z"
submitDate: "2020-08-17T10:43:48.546Z"
  

Как только вы запишете это один раз, вы, вероятно, сможете сделать это через API без графического интерфейса.

… Просто чтобы убедиться, я попробовал это и добился успеха…

введите описание изображения здесь

 import requests

url = "https://forms.office.com/formapi/api/aebbf9f0-23da-49e3-98bf-32171abbc9bc/users/f70e502c-96b2-4239-aca3-764dea371071/forms('8Pm7rtoj40mYvzIXGrvJvCxQDveyljlCrKN2Teo3EHFUQVNaWDlYRkhYR09JRTZWRFpKTTNIQU9HUC4u')/responses"
myobj = {"startDate":"2020-08-17T10:48:40.118Z","submitDate":"2020-08-17T10:48:40.121Z","answers":"[{"questionId":"r8f09d63e6f6f42feb2f8f4f8ed3f9389","answer1":"Hello again, World"},{"questionId":"r28fe12073dfa47399f8ce95ae679dccf","answer1":"F"},{"questionId":"r8f9e9fedcc2e410c80bfa1e0e3ef9750","answer1":"2020-08-26"}]"}

x = requests.post(url, data = myobj)
  

Мои ответы просто жестко закодированы в объекте data, но, похоже, это работает.

Не забудьте указать pip install requests , если у вас его еще нет