pandas read_html ValueError:找不到表

Nom*_*hir 13 html python parsing web-scraping pandas

我正在尝试从“ 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)
Run Code Online (Sandbox Code Playgroud)

我有以下回应:

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
Run Code Online (Sandbox Code Playgroud)

虽然这个页面显然有一个表格,但它没有被 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()
Run Code Online (Sandbox Code Playgroud)

现在的问题是它找不到“tr”。我将不胜感激任何建议。

G. *_*son 15

这是使用 selenium 进行浏览器自动化的解决方案

\n\n
from selenium import webdriver\nimport pandas as pd\ndriver = webdriver.Chrome(chromedriver)\ndriver.implicitly_wait(30)\n\ndriver.get(\'https://www.wunderground.com/personal-weather-station/dashboard?ID=KMAHADLE7#history/tdata/s20170201/e20170201/mcustom.html\')\n    df=pd.read_html(driver.find_element_by_id("history_table").get_attribute(\'outerHTML\'))[0]\n\nTime    Temperature Dew Point   Humidity    Wind    Speed   Gust    Pressure  Precip. Rate. Precip. Accum.  UV  Solar\n0   12:02 AM    25.5 \xc2\xb0C 18.7 \xc2\xb0C 75 %    East    0 kph   0 kph   29.3 hPa    0 mm    0 mm    0   0 w/m\xc2\xb2\n1   12:07 AM    25.5 \xc2\xb0C 19 \xc2\xb0C   76 %    East    0 kph   0 kph   29.31 hPa   0 mm    0 mm    0   0 w/m\xc2\xb2\n2   12:12 AM    25.5 \xc2\xb0C 19 \xc2\xb0C   76 %    East    0 kph   0 kph   29.31 hPa   0 mm    0 mm    0   0 w/m\xc2\xb2\n3   12:17 AM    25.5 \xc2\xb0C 18.7 \xc2\xb0C 75 %    East    0 kph   0 kph   29.3 hPa    0 mm    0 mm    0   0 w/m\xc2\xb2\n4   12:22 AM    25.5 \xc2\xb0C 18.7 \xc2\xb0C 75 %    East    0 kph   0 kph   29.3 hPa    0 mm    0 mm    0   0 w/m\xc2\xb2\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑并细分到底发生了什么,因为上面的一行实际上不是很好的自记录代码:

\n\n

设置驱动程序后,我们选择具有 ID 值的表(幸运的是,该站点实际上使用了合理且描述性的 ID)

\n\n
tab=driver.find_element_by_id("history_table")\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后,从该元素中,我们获取 HTML 而不是 Web 驱动程序元素对象

\n\n
tab_html=tab.get_attribute(\'outerHTML\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们使用pandas来解析html

\n\n
tab_dfs=pd.read_html(tab_html)\n
Run Code Online (Sandbox Code Playgroud)\n\n

来自文档

\n\n
\n

“read_html 返回 DataFrame 对象的列表,即使 HTML 内容中仅包含\n单个表”

\n
\n\n

因此,我们使用我们拥有的唯一表(索引为零)对该列表进行索引

\n\n
df=tab_dfs[0]\n
Run Code Online (Sandbox Code Playgroud)\n


QHa*_*arr 4

您可以使用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/606f3f69777348613/history_20170201null/units:both/v:2.0/q/pws:kmahadle7.jjquerback=jquerback = jquer172024272555555255555559.Callback=jquere 6276

然后,您需要'jQuery1720724027235122559_1542743885015('从前面和');'右侧剥离。然后您就有了一个可以解析的 JSON 字符串。

JSON 示例:

您可以通过在浏览器中使用 F12 开发工具并检查页面加载期间创建的流量的网络选项卡来找到这些 URL。

的一个示例,注意到JSON 中current似乎存在问题,因此我将其替换为:nulls"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)
Run Code Online (Sandbox Code Playgroud)