pandas read_html ValueError: Таблицы не найдены - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь удалить исторические данные о погоде со страницы "https://www.wunderground.com/personal-weather-station/dashboard?ID=KMAHADLE7#history/tdata/s20170201/e20170201/mcustom.html" андеграунда". У меня следующий код:

import pandas as pd 

page_link = 'https://www.wunderground.com/personal-weather-station/dashboard?ID=KMAHADLE7#history/tdata/s20170201/e20170201/mcustom.html'
df = pd.read_html(page_link)
print(df)

У меня следующий ответ:

Traceback (most recent call last):
 File "weather_station_scrapping.py", line 11, in <module>
  result = pd.read_html(page_link)
 File "/anaconda3/lib/python3.6/site-packages/pandas/io/html.py", line 987, in read_html
  displayed_only=displayed_only)
 File "/anaconda3/lib/python3.6/site-packages/pandas/io/html.py", line 815, in _parse raise_with_traceback(retained)
 File "/anaconda3/lib/python3.6/site-packages/pandas/compat/__init__.py", line 403, in raise_with_traceback
  raise exc.with_traceback(traceback)
ValueError: No tables found

Хотя на этой странице явно есть таблица, но она не выбирается read_html. Я пытался использовать Selenium, чтобы страница могла быть загружена до того, как я ее прочитал.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.Firefox()
driver.get("https://www.wunderground.com/personal-weather-station/dashboard?ID=KMAHADLE7#history/tdata/s20170201/e20170201/mcustom.html")
elem = driver.find_element_by_id("history_table")

head = elem.find_element_by_tag_name('thead')
body = elem.find_element_by_tag_name('tbody')

list_rows = []

for items in body.find_element_by_tag_name('tr'):
    list_cells = []
    for item in items.find_elements_by_tag_name('td'):
        list_cells.append(item.text)
    list_rows.append(list_cells)
driver.close()

Сейчаспроблема в том, что он не может найти "tr". Буду признателен за любые предложения.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Вот решение, использующее селен для автоматизации браузера

from selenium import webdriver
import pandas as pd
driver = webdriver.Chrome(chromedriver)
driver.implicitly_wait(30)

driver.get('https://www.wunderground.com/personal-weather-station/dashboard?ID=KMAHADLE7#history/tdata/s20170201/e20170201/mcustom.html')
    df=pd.read_html(driver.find_element_by_id("history_table").get_attribute('outerHTML'))[0]

Time    Temperature Dew Point   Humidity    Wind    Speed   Gust    Pressure  Precip. Rate. Precip. Accum.  UV  Solar
0   12:02 AM    25.5 °C 18.7 °C 75 %    East    0 kph   0 kph   29.3 hPa    0 mm    0 mm    0   0 w/m²
1   12:07 AM    25.5 °C 19 °C   76 %    East    0 kph   0 kph   29.31 hPa   0 mm    0 mm    0   0 w/m²
2   12:12 AM    25.5 °C 19 °C   76 %    East    0 kph   0 kph   29.31 hPa   0 mm    0 mm    0   0 w/m²
3   12:17 AM    25.5 °C 18.7 °C 75 %    East    0 kph   0 kph   29.3 hPa    0 mm    0 mm    0   0 w/m²
4   12:22 AM    25.5 °C 18.7 °C 75 %    East    0 kph   0 kph   29.3 hPa    0 mm    0 mm    0   0 w/m²

Редактирование с разбивкой в ​​точности того, что происходит, поскольку приведенный выше однострочный код на самом деле не очень хороший самодокументированный код:

После настройки драйвера мы выбираем таблицу со значением ее идентификатора (К счастью, этот сайт на самом деле использует разумные и описательные идентификаторы)

tab=driver.find_element_by_id("history_table")

Затем из этого элемента мы получаем HTML вместо элемента веб-драйвераobject

tab_html=tab.get_attribute('outerHTML')

Мы используем pandas для анализа html

tab_dfs=pd.read_html(tab_html)

Из документов :

"read_html возвращает списокобъектов DataFrame, даже если в содержимом HTML содержится только одна таблица "

Таким образом, мы вносим индекс в этот список с единственной таблицей, которая у нас есть, с нулевым индексом

df=tab_dfs[0]
0 голосов
/ 20 ноября 2018

Вы можете использовать requests и не открывать браузер.

Вы можете получить текущие условия, используя:

https://stationdata.wunderground.com/cgi-bin/stationlookup?station=KMAHADLE7&units=both&v=2.0&format=json&callback=jQuery1720724027235122559_1542743885014&_=15

и полосу 'jQuery1720724027235122559_1542743885014(' слева и ')' справа.Затем обработайте строку json.

Вы можете получить сводку и историю, вызвав API со следующим

https://api -ak.wunderground.com / api / 606f3f6977348613 / history_20170201null /Единицы измерения: оба / v: 2.0 / q / pws: KMAHADLE7.json? callback = jQuery1720724027235122559_1542743885015 & _ = 1542743886276

Затем необходимо раздеть 'jQuery1720724027235122559_1542743885015(' спереди и ');' справа.Затем у вас есть строка JSON, которую вы можете проанализировать.

Пример JSON:

image

Эти URL-адреса можно найти с помощью инструментов разработчика F12 в браузере и проверки вкладки сети на предмет трафика, создаваемого во время загрузки страницы.

Пример для current, отмечая, что, похоже, проблема с nulls в JSON, поэтому я заменяю на "placeholder":

import requests
import pandas as pd
import json
from pandas.io.json import json_normalize
from bs4 import BeautifulSoup

url = 'https://stationdata.wunderground.com/cgi-bin/stationlookup?station=KMAHADLE7&units=both&v=2.0&format=json&callback=jQuery1720724027235122559_1542743885014&_=15'
res = requests.get(url)
soup = BeautifulSoup(res.content, "lxml")
s = soup.select('html')[0].text.strip('jQuery1720724027235122559_1542743885014(').strip(')')
s = s.replace('null','"placeholder"')
data= json.loads(s)
data = json_normalize(data)
df = pd.DataFrame(data)
print(df)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...