Как получить дочерние элементы тега span с помощью BeautifulSoup/MechanicalSoup - выбор значений раскрывающегося списка

Я пытаюсь завершить отправку формы на веб-странице (http://supermag.jhuapl.edu/mag/?) с помощью MechanicalSoup. Перед отправкой необходимо указать дату в той же форме, используя раскрывающиеся поля для дня начала, месяца, года, времени и т. д. Это можно сделать с помощью функции set_select() MechanicalSoup, но я не могу получить доступ к соответствующему тегу select для каждого поля. Небольшой отказ от ответственности; хотя у меня есть опыт научного программирования, я новичок в HTML и библиотеках Python, упомянутых выше.

Хотя я не уверен, какую библиотеку лучше всего использовать для выбора даты, я не могу получить доступ к соответствующему тегу select, который является дочерним элементом соответствующих тегов span в форме, с такими атрибутами имени, как «start_day», «start_month».

У меня есть объекты mechanicalsoup.Form(form) и mechanicalsoup.StatefulBrowser(*args, **kwargs) (последний соответствует объекту bs4.BeautifulSoup), и я пробовал:

  • Установка тегов select с помощью set_select от MechanicalSoup
  • Поиск соответствующего тега span и использование BeautifulSoup для доступа к элементам ниже (в частности, к тегам select) с целью каким-то образом выбрать значение, изменив URL-адрес (?)

Отображается фрагмент соответствующего HTML-кода; обратите внимание на теги div и последующие теги select как на дочерние.

Тег формы:

<form name="theForm" class="form-horizontal" onsubmit="return false;">

Соответствующие теги span и select в форме:

<span name="start_time">
  <div>
    <select name="start_day">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>...
    </select>
    <select style="width: 4em;" name="start_month">
      <option value="1">January</option>
      <option...
    </select>
  </div>
</span>

Код находится ниже:

# Opening browser and URL
url = "http://supermag.jhuapl.edu/mag/?"
browser = ms.StatefulBrowser()
browser.open(url)

# Assigning bs4.BeautifulSoup object
html = browser.get_current_page()

# Assigning relevant form
form = browser.select_form('form[name="theForm"]')

# Assign correct span tag for e.g start_time
start_time_span = html.find_all('span')[2]

# Attempt to set start day value - returns
# 'InvalidFormMethod: No select named start_day'
form.set_select({'start_day': 1})

# Attempt to find select tags with bs4
html.find('select', {'start_day': 1})
start_time_span.find('select', {'start_day': 1})

# and eg looking for contents returns empty list
start_time_span.contents

Я ожидал, что теги select будут перечислены в попытках find() bs4, или чтобы set_select() Mechanicalsoup получил доступ и установил данный тег select при вызове в правильной форме.

Тег span находится в HTML BeautifulSoup, но, похоже, не имеет дочерних тегов select, которые присутствуют в исходном HTML и необходимы для выбора даты. Вызов set_select() возвращает ошибку о том, что тег не найден.

Заранее спасибо; это мой первый вопрос в StackOverflow, и я надеюсь, что он достаточно хорошо соответствует рекомендациям!


person Dagorodir    schedule 27.03.2019    source источник


Ответы (1)


Для меня ваш код в целом выглядит нормально! Когда я запускаю ваш фрагмент кода Python в HTML-коде, который вы здесь цитируете, он не вызывает исключения InvalidFormMethod. Однако, когда я запускаю его по указанному вами URL-адресу, я вижу эту ошибку (потому что, глядя на исходный HTML, нет элемента с именем start_day).

Я подозреваю, что это связано с тем, что определенное действие JavaScript генерирует HTML, который включает поле start_day. На это намекает форма, имеющая атрибут onsubmit и не имеющая action, а также включающая множество файлов JavaScript (которые могут быть или не быть необходимыми для взаимодействия с формой). В зависимости от того, что именно вы хотите делать с этой формой, вам, вероятно, потребуется использовать инструмент, поддерживающий JavaScript, например Selenium (MechanicalSoup не поддерживает — см. эти вопросы и ответы).

person Daniel Hemberger    schedule 27.03.2019
comment
Спасибо за Ваш ответ. Похоже, мне придется узнать немного больше об отправке форм в HTML и обнаружении JavaScript! У меня есть быстрое хакерское решение моей проблемы - ввод даты вручную в строку, отформатированную как URL-адрес, выводимый событиями JavaScript, например: http://supermag.jhuapl.edu/mag/?start=2015-01-22T20%3A50%3A30Z&interval=0%3A24%3A00&stations=NAL%2CLYR%2CHOP%2CBJN%2CHRN%2CBBG&tab=download&baseline=all&delta=none", и открытие браузера MechanicalSoup отсюда. Кнопка загрузки также имеет событие JavaScript — нужен ли мне Selenium и здесь? - person Dagorodir; 27.03.2019
comment
Вместо подделки URL вы также можете использовать new_control для создания элементов управления, как это делает JavaScript. Вы почти всегда можете имитировать то, что делает javascript, но вам нужно заново делать то, что делают скрипты, вручную, поэтому возможность выполнения без Selenium зависит от того, сколько JavaScript требуется для работы сайта, и сколько времени вы готов инвестировать в него. - person Matthieu Moy; 28.03.2019