Puedo obtener los datos de la tabla HTML, pero ¿cómo obtendría solo los datos que necesito? Por ejemplo, ¿cómo leería solo '10 o más sm (16+ km) '? Línea 7?

KBWI (Baltimore-Washington, MD, US)
KBWI 301254Z 10007KT 10SM SCT017 BKN023 OVC039 21/18 A3027 RMK AO2 SLP249 T02060178
20.6°C ( 69°F)
17.8°C ( 64°F) [RH =  84%]
30.27 inches Hg (1025.1 mb) [Sea level pressure: 1024.9 mb]
from the E (100 degrees) at   8 MPH (7 knots;  3.6 m/s)
10 or more sm (16+ km)
2300 feet AGL
scattered clouds at 1700 feet AGL, broken clouds at 2300 feet AGL, overcast cloud deck at 3900 feet AGL

page = urlopen(metar_link)
soup = BeautifulSoup(page, 'html.parser')
table = soup.find('table')

for tr in table.find_all('tr'):
    metar = tr.find_all('td')[1].text.strip()
    print(metar)
1
Matt Damoz 30 sep. 2019 a las 18:03

4 respuestas

La mejor respuesta

Supongo que desea los datos después del intervalo Visibility.

Entonces puedes hacer algo como esto:

import requests
from bs4 import BeautifulSoup as soup

url = "https://www.aviationweather.gov/metar/data?ids=kbwi&format=decoded&date=&hours=0"
resp = requests.get(url)

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

table = page.find('table')
activate_print = ['Visibility:']

save_flag = False
for td in table.find_all('td'):
    if save_flag:
        print(td.text)
        save_flag = False
    if td.find('span') and td.find('span').text in activate_print:
        save_flag = True

resultado:

10 or more sm (16+ km)

Por supuesto, si quieres algo más, solo tienes que hacer la misma lógica y agregar una etiqueta dentro de la lista activate_print

1
Maaz 30 sep. 2019 a las 15:17

Pruebe esto solo con la etiqueta td.

print(table.find_all('td')[13].text.strip())

Código:

page = urlopen(metar_link)
soup = BeautifulSoup(page, 'html.parser')
table = soup.find('table')
print(table.find_all('td')[13].text.strip())

O puede encontrar la etiqueta span Visibility y luego encontrar la siguiente etiqueta td.

from bs4 import BeautifulSoup
import requests
page = requests.get("https://www.aviationweather.gov/metar/data?ids=kbwi&format=decoded&date=&hours=0")
soup = BeautifulSoup(page.text, 'html.parser')
table = soup.find('table')
print(table.find('span',text='Visibility:').find_next('td').text.strip())

Salida:

10 or more sm (16+ km)
0
KunduK 30 sep. 2019 a las 16:58

Una manera sucinta con bs4 4.7.1+ es usar: contiene y un combinador de hermanos adyacente

import requests
from bs4 import BeautifulSoup as bs

r = requests.get('https://www.aviationweather.gov/metar/data?ids=kbwi&format=decoded&date=&hours=0')
soup = bs(r.content, 'lxml')
print(soup.select_one('td:contains("Visibility:") + td').text)
0
QHarr 30 sep. 2019 a las 17:08

También puede leerlo en un marco de datos (ya que es una etiqueta <table>) y filtrar de esa manera.

import pandas as pd

url = "https://www.aviationweather.gov/metar/data?ids=kbwi&format=decoded&date=&hours=0"

df = pd.read_html(url)[0]
df[df[0] == 'Visibility:'][1]
1
chitown88 30 sep. 2019 a las 15:50
58170569