我一直在使用pandas并请求提取一些表来获取NFL统计数据。它一直很顺利,我已经能够从其他网站拉桌子,直到我试图从这个特定网站获得NFL组合表。
它在df_list = pd.read_html(html)
我得到的错误是:
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U1') dtype('<U1') dtype('<U1')
以下是我在其他网站上使用的代码,这些代码效果非常好。
import requests
import pandas as pd
df = pd.DataFrame()
url = 'http://nflcombineresults.com/nflcombinedata_expanded.php?
year=1987&pos=&college='
html = requests.get(url).content
df_list = pd.read_html(html)
df = df_list[-1]
我已经阅读并看到了一些关于BeautifulSoup的内容,但pd.read_html()
的简洁性非常好而且紧凑。所以我不知道是否有一个我不知道的快速修复,或者我是否需要在1987年至2017年期间深入了解BeautifulSoup来获取这些表格。
答案 0 :(得分:1)
这不短,但可能更强大:
import requests
import pandas as pd
from bs4 import BeautifulSoup
便利功能:
def souptable(table):
for row in table.find_all('tr'):
yield [col.text for col in row.find_all('td')]
返回一个DataFrame,其中包含为给定年份加载的数据:
def getyear(year):
url = 'http://nflcombineresults.com/nflcombinedata_expanded.php?year=%d&pos=&college=' % year
r = requests.get(url)
soup = BeautifulSoup(r.text, 'lxml')
data = list(souptable(soup.table))
df = pd.DataFrame(data[1:], columns=data[0])
df = df[pd.notnull(df['Name'])]
return df.apply(pd.to_numeric, errors="ignore")
此函数在创建DataFrame时切出标题行,使用第一行作为列名,并过滤掉任何具有空Name值的行。
最后,将所需的多年连接到单个DataFrame中:
dfs = pd.concat([getyear(year) for year in range(1987, 1990)])
答案 1 :(得分:0)
确定。做了一些更多的研究。我看起来问题是最后一行是一个合并的单元格,这可能是问题的来源。所以我确实开始使用BeautifulSoup来提取数据。这是我的解决方案:
import requests
import pandas as pd
from bs4 import BeautifulSoup
我想从1987年到2017年每年拉一次
seasons = list(range(1987, 2018))
df = pd.DataFrame()
temp_df = pd.DataFrame()
所以它会贯穿每一年。将每个单元格附加到新行。然后再次知道最后一个单元格是&#34;空白&#34;,我通过在数据框循环之前将数据框定义为df[:-1]
来消除最后一行,并附加下一年的数据。
for i in seasons:
df = df[:-1]
url = 'http://nflcombineresults.com/nflcombinedata_expanded.php?
year=%s&pos=&college=' % (i)
r = requests.get(url)
soup = BeautifulSoup(r.text, 'lxml')
for tr in soup.table.find_all('tr'):
row = [td.text for td in tr.find_all('td')]
temp_df = row
df = df.append(temp_df, ignore_index = True)
最后,由于没有新的一年要追加,我需要消除最后一行。然后我将数据帧重新整形为16列,重命名第一行中的列,然后消除数据帧中的行标题。
df = df[:-1]
df = (pd.DataFrame(df.values.reshape(-1, 16)))
df.columns = df.iloc[0]
df = df[df.Name != 'Name']
我还在学习python,所以任何意见,建议,任何尊重的建设性批评都会受到欢迎。也许有更好,更合适的解决方案?