Красивый суп l oop над элементом div в HTML - PullRequest
0 голосов
/ 17 марта 2020

Я пытаюсь использовать Beautiful Soup для извлечения некоторых значений из веб-страницы (здесь не очень много мудрости), которые являются почасовыми значениями из прогноза Weatherbug . В режиме разработчика Chrome я вижу, что значения вложены в классы div, как показано во фрагменте ниже:

enter image description here

В Python Я могу попытаться имитировать c веб-браузер и найти следующие значения:

import requests
import bs4 as BeautifulSoup
import pandas as pd
from bs4 import BeautifulSoup

url = 'https://www.weatherbug.com/weather-forecast/hourly/san-francisco-ca-94103'

header = {
  "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36",
  "X-Requested-With": "XMLHttpRequest"
}

page = requests.get(url, headers=header)

soup = BeautifulSoup(page.text, 'html.parser')

С помощью приведенного ниже кода я могу найти 12 из этих hour-card_mobile_cond классов div, которые выглядят примерно так же, как и при поиске Почасовой прогноз Я могу видеть 12 часов / переменных будущих данных. Я не уверен, почему я выбираю метод мобильного устройства для просмотра ... (?)

temp_containers = soup.find_all('div', class_ = 'hour-card__mobile__cond')
print(type(temp_containers))
print(len(temp_containers))

Вывод:

<class 'bs4.element.ResultSet'>
12

Я делаю что-то неправильно ниже, если я пытаюсь составьте некоторый код для l oop через все эти классы div, чтобы погрузиться немного дальше ... Я могу вернуть 12 пустых списков .. У кого-нибудь будет совет, где я могу улучшить? В конечном счете, я хочу поместить все 12 будущих прогнозируемых значений в час в pandas фрейм данных.

for div in temp_containers:
    a = div.find_all('div', class_ = 'temp ng-binding')
    print(a)

РЕДАКТИРОВАТЬ, полный код основан на ответе с pandas dataframe

import requests
from bs4 import BeautifulSoup
import pandas as pd


r = requests.get(
    "https://www.weatherbug.com/weather-forecast/hourly/san-francisco-ca-94103")
soup = BeautifulSoup(r.text, 'html.parser')

stuff = []

for item in soup.select("div.hour-card__mobile__cond"):
    item = int(item.contents[1].get_text(strip=True)[:-1])
    print(item)
    stuff.append(item)


df = pd.DataFrame(stuff)
df.columns = ['temp']

Ответы [ 2 ]

0 голосов
/ 17 марта 2020

Когда вы видите class = "temp ng-binding", это означает, что у div есть класс "temp" и "ng-binding", поэтому поиск обоих не будет работать. Кроме того, когда я запускал ваш скрипт, html временных контейнеров выглядел примерно так:

print(temp_containers[0])

<div class="temp">
                    51°
</div>

, поэтому я запустил это и получил результаты

import requests
import pandas as pd
from bs4 import BeautifulSoup

url = 'https://www.weatherbug.com/weather-forecast/hourly/san-francisco-ca-94103'

header = {
  "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36",
  "X-Requested-With": "XMLHttpRequest"
}

page = requests.get(url, headers=header)

soup = BeautifulSoup(page.text, 'html.parser')

temp_containers = soup.find_all('div', class_ = 'hour-card__mobile__cond')
print(type(temp_containers))
print(len(temp_containers))

for div in temp_containers:
    a = div.find('div', class_ = 'temp')
    print(a.text)
0 голосов
/ 17 марта 2020

Сайт загружается через JavaScript динамически после загрузки страницы. так что вы можете использовать запросы- html или selenium.

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

options = Options()
options.add_argument('--headless')
driver = webdriver.Firefox(options=options)

driver.get(
    "https://www.weatherbug.com/weather-forecast/hourly/san-francisco-ca-94103")


data = driver.find_elements_by_css_selector("div.temp.ng-binding")

for item in data:
    print(item.text)

driver.quit()

Вывод:

51°

52°

53°

54°

53°

53°

52°

51°

51°

50°

50°

49°

Обновление по запросу пользователя:

import requests
from bs4 import BeautifulSoup

r = requests.get(
    "https://www.weatherbug.com/weather-forecast/hourly/san-francisco-ca-94103")
soup = BeautifulSoup(r.text, 'html.parser')

for item in soup.select("div.hour-card__mobile__cond"):
    item = int(item.contents[1].get_text(strip=True)[:-1])
    print(item, type(item))

Выход:

51 <class 'int'>
52 <class 'int'>
53 <class 'int'>
53 <class 'int'>
53 <class 'int'>
53 <class 'int'>
52 <class 'int'>
51 <class 'int'>
51 <class 'int'>
50 <class 'int'>
50 <class 'int'>
50 <class 'int'>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...