Как создать веб-данные с веб-страницы с помощью динамического HTML (Python)?

#javascript #python #html #web-scraping #dynamic-html

#javascript #python #HTML #вебскрапирование #dynamic-html

Вопрос:

Я пытаюсь выяснить, как очистить данные со следующего URL: https://www.aap.org/en-us/advocacy-and-policy/aap-health-initiatives/nicuverification/Pages/NICUSearch.aspx

Вот тип данных:

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

Похоже, что все заполняется из базы данных и загружается на веб-страницу с помощью javascript.

Я делал что-то подобное в прошлом, используя selenium и PhantomJS , но я не могу понять, как получить эти поля данных в Python.

Как и ожидалось, я не могу использовать pd.read_html для решения проблем такого типа.

Возможно ли проанализировать результаты из:

 from selenium import webdriver

url="https://www.aap.org/en-us/advocacy-and-policy/aap-health-initiatives/nicuverification/Pages/NICUSearch.aspx"

browser = webdriver.PhantomJS()
browser.get(url)
content = browser.page_source
  

Или, может быть, для доступа к фактическим базовым данным?

Если нет, то каковы другие подходы, кроме копирования и вставки в течение нескольких часов?

Редактировать:

Основываясь на приведенном ниже ответе, от @thenullptr я смог получить доступ к материалу, но только на странице 1. Как я могу адаптировать это для просмотра всех страниц [рекомендации по правильному анализу]? Моя конечная цель — иметь это в фрейме данных pandas

 import requests
from bs4 import BeautifulSoup

r = requests.post(
    url = 'https://search.aap.org/nicu/', 
    data = {'SearchCriteria.Level':'1', 'X-Requested-With':'XMLHttpRequest'}, 

) #key:value
html = r.text

# Parsing the HTML
    soup = BeautifulSoup(html.split("</script>")[-1].strip(), "html")
div = soup.find("div", {"id": "main"})

div = soup.findAll("div", {"class":"blue-border panel list-group"})
def f(x):
    ignore_fields = ['Collapse all','Expand all']
    output = list(filter(bool, map(str.strip, x.text.split("n"))))
    output = list(filter(lambda x: x not in ignore_fields, output))
    return output
results = pd.Series(list(map(f, div))[0])
  

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

1. Если вы используете webdriver, которым вы можете воспользоваться browser.find_elements_by_class_name('yourClassName') , и если вам нужно дождаться загрузки этих элементов, вы можете обойтись WebDriverWait(browser,secondsToWaitFloat) . Когда вы находите элементы по имени класса, вы получаете список элементов, к которым вы можете обратиться get_attribute('innerText') , чтобы получить внутренний текст.

2. Попробуйте использовать вкладку сеть в инструментах разработчика вашего браузера, чтобы просмотреть, какие вызовы XHR выполняются. Вероятно, существует общедоступный API, из которого страница получает информацию, которую вы можете извлечь.

3. @thenullptr есть несколько XHR объектов. Вот представление: i.imgur.com/BddXtgA.png Как я могу получить к ним доступ? Что бы я искал в частности (извините, я никогда раньше не использовал эти объекты).

4. @libby Как бы вы порекомендовали найти классы? У меня есть inspected отдельные элементы, использующие Google Chrome. Я нашел <div class="col-md-7"><label>Email address: </label>emailaddresshere</div> , например, чтобы получить адрес электронной почты. Будет ли вызываться класс, который я ищу col-md-7 . Можете ли вы показать пример, как я мог бы извлечь эту информацию? Спасибо.

5. @O.rka Я думаю, это может помочь: imgur.com/a/C4fJQhn Насколько я могу судить, страница ( search.aap.org/nicu ) принимает запрос POST для поиска, затем, как вы можете видеть на скриншоте, страница отвечает HTML-кодом, который вы можете увидеть на вкладке ответа.

Ответ №1:

Чтобы следовать моему последнему комментарию, приведенное ниже должно дать вам хорошую отправную точку. Просматривая вызовы XHR, вы просто хотите посмотреть, какие данные отправляются и принимаются от каждого из них, чтобы точно определить тот, который вам нужен. Ниже приведены необработанные данные POST, отправляемые в API при выполнении поиска, похоже, вам нужно использовать хотя бы один и включить последний.

 {
    "SearchCriteria.Name": "smith",
    "SearchCriteria.City": "",
    "SearchCriteria.State": "",
    "SearchCriteria.Zip": "",
    "SearchCriteria.Level": "",
    "SearchCriteria.LevelAssigner": "",
    "SearchCriteria.BedNumberRange": "",
    "X-Requested-With": "XMLHttpRequest"
}
  

Вот простой пример того, как вы можете отправить post-запрос, используя библиотеку запросов, веб-страница ответит необработанными данными, чтобы вы могли использовать BS или аналогичный для их анализа, чтобы получить необходимую информацию.

 import requests
r = requests.post('https://search.aap.org/nicu/', 
data = {'SearchCriteria.Name':'smith', 'X-Requested-With':'XMLHttpRequest'}) #key:value
print(r.text)
  

С принтами <strong class="col-md-8 white-text">JOHN PETER SMITH HOSPITAL</strong>...

https://requests.readthedocs.io/en/master/user/quickstart/

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

1. Спасибо за это. Какую часть вы на самом деле используете data dictionary?

2. данные — это просто параметр функции post, например. r = requests.post('https://httpbin.org/post', data = {'key':'value'}) если это то, что вы имеете в виду

3. о, я не знаю, как я этого не уловил. Вы рекомендуете какой-либо способ анализа r.text ? Я подумал, что наиболее эффективный способ сделать это — начать с BedNumberRange 1, а затем двигаться вверх. Это HTML или выводимый Java-скрипт? Сначала я подумал, что это XML, и попытался использовать XML-деревья, но формат был отключен.

4. Я пытаюсь использовать BeautifulSoup : soup = BeautifulSoup(html.split("</script>")[-1].strip(), "html") div = soup.find("div", {"id": "main"}) это лучший способ анализа результатов? Я не уверен, как использовать поиск по имени, поскольку я нашел имя, а затем искал, но не получил результатов. Хотя ваш пример smith работает отлично.

5. Я также не понимаю, как получить доступ к разным номерам страниц