2017-08-01 13 views
0

私は美味しいスープとネストしたテーブルを使い慣れていないので、私はウィキペディアのテーブルを掻き集める経験を得るようにしています。美味しいスープWikipidiaネストしたテーブル

私はウェブ上の良い例を探しましたが、残念ながら何も見つかりませんでした。

私の目標は、このweb pageの「アメリカの国」という表をパンダで解析することです。私のコードからわかるように、以下の問題があります。

1)すべての列を抽出できません。どうやら私のコードでは、pandas DataFrameですべての列を正しくインポートすることができず、最初の列の下にhtmlテーブルの3番目の列のエントリが書き込まれます。

2)私はテーブルのいくつかの行に表示されますはcolspan =「2」に対処する方法がわかりません。私のパンダDataFrameでは、大都市と大都市が同じときに同じエントリーをしたいと思います。

ここに私のコードです。私が最初の問題を克服しようとしていることに注意してください。

コード:

from urllib.request import urlopen 
import pandas as pd 

wiki='https://en.wikipedia.org/wiki/List_of_states_and_territories_of_the_United_States' 
page = urlopen(wiki) 

from bs4 import BeautifulSoup 

soup = BeautifulSoup(page) 

right_table=soup.find_all('table')[0] # First table 

rows = right_table.find_all('tr')[2:] 

A=[] 
B=[] 
C=[] 
D=[] 
F=[] 

for row in rows: 
    cells = row.findAll('td') 
# print(len(cells)) 
    if len(cells)>=11: #Only extract table body not heading 
     A.append(cells[0].find(text=True)) 
     B.append(cells[1].find(text=True)) 
     C.append(cells[2].find(text=True)) 
     D.append(cells[3].find(text=True)) 
     F.append(cells[4].find(text=True)) 

df=pd.DataFrame(A,columns=['State']) 
df['Capital']=B 
df['Largest']=C 
df['Statehood']=D 
df['Population']=F 
df 
print(df) 

ごsuggestingsを持っていますか? BeautifulSoupの方が良いことを理解する助けとなります。 ありがとうございます。

+0

これらウィキペディアのテーブルがFYI編集した人間ですです。彼らはしばしば混乱していることを意味します。 – pguardiario

答えて

1

ここで私が使用する戦略です。

テーブルの各行は完成していますが、いくつかの行には「都市」列に2つの都市があり、いくつかの列には1つしかないことがわかります。これは、行の項目数を使用して、その行に記載されている都市名を「倍」する必要があるかどうかを判断できることを意味します。

私はあなたのやり方を始めます。

>>> import requests 
>>> import bs4 
>>> page = requests.get('https://en.wikipedia.org/wiki/List_of_states_and_territories_of_the_United_States').content 
>>> soup = bs4.BeautifulSoup(page, 'lxml') 
>>> right_table=soup.find_all('table')[0] 

次に、テーブルのすべての行を見つけ、それが少なくともほぼ正しいことを確認します。

>>> trs = right_table('tr') 
>>> len(trs) 
52 

私はアラバマ州とワイオミング州の行を見つけるまでは、最初と最後の行をつつくと、そのテキストを表示します。それらは2種類の行の例です!

>>> trs[2].text 
'\n\xa0Alabama\nAL\nMontgomery\nBirmingham\n\nDec 14, 1819\n\n\n4,863,300\n\n52,420\n135,767\n50,645\n131,171\n1,775\n4,597\n\n7\n\n' 
>>> trs[51].text 
'\n\xa0Wyoming\nWY\nCheyenne\n\nJul 10, 1890\n\n\n585,501\n\n97,813\n253,335\n97,093\n251,470\n720\n1,864\n\n1\n\n' 

私は\n\xa0にこれらの文字列を分割することができていることに気づきます。これは正規表現で行うことができます。これらのリストの内包表記で

>>> [_ for _ in re.split(r'[\n\xa0]', trs[51].text) if _] 
['Wyoming', 'WY', 'Cheyenne', 'Jul 10, 1890', '585,501', '97,813', '253,335', '97,093', '251,470', '720', '1,864', '1'] 
>>> [_ for _ in re.split(r'[\n\xa0]', trs[2].text) if _] 
['Alabama', 'AL', 'Montgomery', 'Birmingham', 'Dec 14, 1819', '4,863,300', '52,420', '135,767', '50,645', '131,171', '1,775', '4,597', '7'] 

if _条件は、空の文字列を破棄することです。

ワイオミングの文字列の長さは12、アラバマの文字数は13です。私はアラバマの文字列をパンダのままにしておきます。

>>> row = [_ for _ in re.split(r'[\n\xa0]', trs[51].text) if _] 
>>> row[:3]+row[2:] 
['Wyoming', 'WY', 'Cheyenne', 'Cheyenne', 'Jul 10, 1890', '585,501', '97,813', '253,335', '97,093', '251,470', '720', '1,864', '1'] 
0

ワイオミング州(そして他のすべての長さ12)を拡張します。下記の解決策では、両方の問題を解決する必要があります。

from urllib.request import urlopen 
import pandas as pd 
from bs4 import BeautifulSoup 

wiki='https://en.wikipedia.org/wiki/List_of_states_and_territories_of_the_United_States?action=render' 
page = urlopen(wiki) 
soup = BeautifulSoup(page, 'html.parser') 
right_table=soup.find_all('table')[0] # First table 
rows = right_table.find_all('tr')[2:] 

A=[] 
B=[] 
C=[] 
D=[] 
F=[] 

for row in rows: 
    cells = row.findAll('td') 
    combine_cells = cells[1].get('colspan') # Tells us whether columns for Capital and Established are the same 
    cells = [cell.text.strip() for cell in cells] # Extracts text and removes whitespace for each cell 
    index = 0 # allows us to modify columns below 

    A.append(cells[index]) # State Code 
    B.append(cells[index + 1]) # Capital 
    if combine_cells: # Shift columns over by one if columns 2 and 3 are combined 
     index -= 1 

    C.append(cells[index + 2]) # Largest 
    D.append(cells[index + 3]) # Established 
    F.append(cells[index + 4]) # Population 

df=pd.DataFrame(A,columns=['State']) 
df['Capital']=B 
df['Largest']=C 
df['Statehood']=D 
df['Population']=F 
df 
print(df) 

編集:ここでは、上記のコードのクリーンバージョン

import pandas as pd 
from bs4 import BeautifulSoup 
from urllib.request import urlopen 

wiki = 'https://en.wikipedia.org/wiki/List_of_states_and_territories_of_the_United_States' 
page = urlopen(wiki) 
soup = BeautifulSoup(page, 'html.parser') 
table_rows = soup.find('table')('tr')[2:] # Get all table rows 
cells = [row('td') for row in table_rows] # Get all cells from rows 


def get(cell): # Get stripped string from tag 
    return cell.text.strip() 


def is_span(cell): # Check if cell has the 'colspan' attribute <td colspan="2"></td> 
    return cell.get('colspan') 


df = pd.DataFrame() 
df['State'] = [get(cell[0]) for cell in cells] 
df['Capital'] = [get(cell[1]) for cell in cells] 
df['Largest'] = [get(cell[2]) if not is_span(cell[1]) else get(cell[1]) for cell in cells] 
df['Statehood'] = [get(cell[3]) if not is_span(cell[1]) else get(cell[2]) for cell in cells] 
df['Population'] = [get(cell[4]) if not is_span(cell[1]) else get(cell[3]) for cell in cells] 
print(df) 
+0

ありがとうございます!非常に有用なコメント! – fdrigo

関連する問題