2017-04-20 15 views
1

私は美しいスープを使ってhtmlテーブルを掻き集め、パンダにそれをインポートしようとしています - http://www.baseball-reference.com/teams/NYM/2017.shtml - "チームバッティング"テーブル。テーブルを検索美しいスープでhtmlテーブルをスクラップしてパンダに

は問題ありません:データの行を見つける

table = soup.find('div', attrs={'class': 'overthrow table_container'}) 
table_body = table.find('tbody') 

は、いずれかの問題ではありません。

for i in table.findAll('tr')[2]: #increase to 3 to get next row in table... 
    print(i.get_text()) 

そして私も、ヘッダーの名前を見つけることができます。

table_head = table.find('thead') 

for i in table_head.findAll('th'): 
    print(i.get_text()) 

今、データフレームにすべてをまとめるのに問題があります。これまで私がこれまで持っていたことは次のとおりです。

header = []  
for th in table_head.findAll('th'): 
     key = th.get_text() 
     header.append(key) 

row= [] 
for tr in table.findAll('tr')[2]: 
    value = tr.get_text() 
    row.append(value) 

od = OrderedDict(zip(head, row)) 
df = pd.DataFrame(d1, index=[0]) 

これは、一度に1つの行に対してのみ機能します。私の質問は、どのように私は同時にテーブルのすべての行のためにこれを行うことができますか?

答えて

1

私はあなたの目的のために以下が動作することをテストしました。基本的には、リストを作成し、プレイヤーをループさせ、そのリストを使用してDataFrameを作成する必要があります。 DataFrame行を行単位で作成しないことは、おそらく大幅に遅くなることがあります。

import collections as co 
import pandas as pd 

from bs4 import BeautifulSoup 

with open('team_batting.html','r') as fin: 
    soup = BeautifulSoup(fin.read(),'lxml') 

table = soup.find('div', attrs={'class': 'overthrow table_container'}) 
table_body = table.find('tbody') 

table_head = table.find('thead') 
header = []  
for th in table_head.findAll('th'): 
    key = th.get_text() 
    header.append(key) 

# loop over table to find number of rows with '' in first column 
endrows = 0 
for tr in table.findAll('tr'): 
    if tr.findAll('th')[0].get_text() in (''): 
     endrows += 1 

rows = len(table.findAll('tr')) 
rows -= endrows + 1 # there is a pernicious final row that begins with 'Rk' 

list_of_dicts = [] 
for row in range(rows): 
    the_row = [] 
    try: 
     table_row = table.findAll('tr')[row] 
     for tr in table_row: 
      value = tr.get_text() 
      the_row.append(value) 
     od = co.OrderedDict(zip(header,the_row)) 
     list_of_dicts.append(od) 
    except AttributeError: 
     continue 

df = pd.DataFrame(list_of_dicts) 
+0

偉大な答えをありがとう。この行には「[row]」という名前がありますか?table_row = table.findAll( 'tr')[row] ---以前のようにこのように使用されたことはありませんでした。 – e9e9s

+0

大歓迎です。この場合のインデックスだけです。 '' table_row = table.findAll( 'tr')[0] 'または' table_row = table.findAll( 'tr')[1] ' – bernie

+0

に相当します。この行から' [row] 'が除外され、 'table_row'を反復することができないでしょうか? – e9e9s

0

このソリューションは、pandasを使用していますが、それはチームバッティングテーブルが第十テーブルであることを事前に知ることによって少しを騙し。その知識を用いて、以下の用途pandasread_html機能と返さDataFrameオブジェクトのリストから第十DataFrameをつかみます。残りの部分はデータクリーニングの一部です:

import pandas as pd 


url = 'http://www.baseball-reference.com/teams/NYM/2017.shtml' 

# Take 10th dataframe 
team_batting = pd.read_html(url)[9] 

# Take columns whose names don't contain "Unnamed" 
team_batting.drop([x for x in team_batting.columns if 'Unnamed' in x], axis=1, inplace=True) 

# Remove the rows that are just a copy of the headers/columns 
team_batting = team_batting.ix[team_batting.apply(lambda x: x != team_batting.columns,axis=1).all(axis=1),:] 

# Take out the Totals rows 
team_batting = team_batting.ix[~team_batting.Rk.isnull(),:] 

# Get a glimpse of the data 
print(team_batting.head(5)) 

# Rk Pos    Name Age G PA AB R H 2B ... OBP SLG OPS OPS+ TB GDP HBP SH SF IBB 
# 0 1 C Travis d'Arnaud 28 12 42 37 6 10 2 ... .357 .541 .898 144 20 1 1 0 0 1 
# 1 2 1B  Lucas Duda* 31 13 50 42 4 10 2 ... .360 .571 .931 153 24 1 0 0 0 2 
# 2 3 2B  Neil Walker# 31 14 62 54 5 12 3 ... .306 .278 .584 64 15 2 0 0 1 0 
# 3 4 SS Asdrubal Cabrera# 31 15 67 63 10 17 2 ... .313 .397 .710 96 25 0 0 0 0 0 
# 4 5 3B  Jose Reyes# 34 15 59 53 3 5 2 ... .186 .132 .319 -9 7 0 0 0 0 0 

私はこれが役立つことを望みます。

関連する問題