2015-12-04 2 views
2

У меня есть следующий HTML:BeautifulSoup метки диапазона идентификатор панды

</tr><tr> 
<td> 
<span id="Grid_exdate_43">2/15/2005</span> 
</td><td>Cash</td><td> 
<span id="Grid_CashAmount_43">0.08</span> 
</td><td> 
<span id="Grid_DeclDate_43">--</span> 
</td><td> 
<span id="Grid_RecDate_43">2/17/2005</span> 
</td><td> 
<span id="Grid_PayDate_43">3/10/2005</span> 
</td> 
</tr><tr> 
<td> 
<span id="Grid_exdate_44">11/15/2004</span> 
</td><td>Cash</td><td> 
<span id="Grid_CashAmount_44">3.08</span> 
</td><td> 
<span id="Grid_DeclDate_44">--</span> 
</td><td> 
<span id="Grid_RecDate_44">11/17/2004</span> 
</td><td> 
<span id="Grid_PayDate_44">12/2/2004</span> 
</td> 
</tr><tr> 

Каждая секция имеет те же 5 элементов, а именно: Grid_exdate, Grid_CashAmount, Grid_DeclDate, Grid_RecDate, Grid_PayDate. Каждый id каждого раздела имеет целое число, следующее за ним, которое увеличивается для каждого раздела. В приведенном выше примере мы имеем разделы 43 и 44.

Мне нужно сохранить каждую секцию в виде строки в кадре данных pandas. Информационная рамка будет следующей:

Grid_exdate Grid_CashAmount Grid_DeclDate Grid_RecDate Grid_PayDate 
2/15/2005  0.08    --    2/17/2005  3/10/2005 
11/15/2004 3.08    --    11/17/2004  12/2/2004 

Я не понимаю, как это сделать.

EDIT:

Хорошо, что мне удалось понять что-то, что должно работать:

def get_exdate(self, id): 
    return id and re.compile("Grid_exdate_").search(id) 

df = pd.DataFrame() 
exdate_list = [] 
for link in soup.find_all(id=self.get_exdate): 
    exdate_list.append(link.string) 

df['Grid_exdate'] = exdate_list 

Таким образом, приведенный выше код получает все Grid_exdate_ значения, используя регулярное выражение, добавляя все результаты в список, а затем добавив это как столбец в dataframe.

Так просто создайте 5 из них, по одному для каждого поля. Если у кого-то есть лучшее решение, сообщите мне (это, вероятно, не очень эффективный способ сделать это). В противном случае это должно сделать трюк.

+1

Почему ['read_html'] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_html.html) не разрешает вашу проблему? – memoselyk

ответ

0

Спасибо всем за предложенные решения. В конце концов я пошел с, после чего, кажется, был наименее сложным решением:

def get_exdate(self, id): 
    return id and re.compile("Grid_exdate_").search(id) 

df = pd.DataFrame() 
exdate_list = [] 
for link in soup.find_all(id=self.get_exdate): 
    exdate_list.append(link.string) 

df['Grid_exdate'] = exdate_list 

Это производит поиск HTML/суп для всего, начиная с Grid_exdate_ использованием re.compile. Затем добавьте результаты в dataframe. Поэтому я только что создал re.compile для поиска каждого из обязательных полей и добавил их все в dataframe с правильными заголовками столбцов.

1

Вы можете использовать панда read_html из документации:

Этой функция ищет <table> элементов и только для <tr> и <th> строк и <td> элементов внутри каждый <tr> или <th> элемента в таблице. <td> означает «данные таблицы».

Так, прежде чем использовать файл, который нужно обернуть его <table> тег:

<table> 
your html 
</table> 

затем использовать первый элемент, потому что read_html читает таблицы из HTML в список:

df = pd.read_html('file.html') 

In [444]: df[0] 
Out[444]: 
      0  1  2 3   4   5 
0 2/15/2005 Cash 0.08 -- 2/17/2005 3/10/2005 
1 11/15/2004 Cash 3.08 -- 11/17/2004 12/2/2004 

EDIT

Если вы хотите переименовать столбцы :

df1 = df[0] 
df1.columns = ["Grid_exdate", "Cash", "Grid_CashAmount", "Grid_DeclDate", "Grid_RecDate", "Grid_PayDate"] 

Вы будете иметь 'Cash' колонку, потому что у вас есть в виде отдельной ячейки таблицы:

In [494]: df1 
Out[494]: 
    Grid_exdate Cash Grid_CashAmount Grid_DeclDate Grid_RecDate Grid_PayDate 
0 2/15/2005 Cash    0.08   -- 2/17/2005 3/10/2005 
1 11/15/2004 Cash    3.08   -- 11/17/2004 12/2/2004 

Вы тогда может упасть столбец 'Cash' или изменить ваш первоначальный стол

In [496]: df1.drop('Cash', axis=1) 
Out[496]: 
    Grid_exdate Grid_CashAmount Grid_DeclDate Grid_RecDate Grid_PayDate 
0 2/15/2005    0.08   -- 2/17/2005 3/10/2005 
1 11/15/2004    3.08   -- 11/17/2004 12/2/2004 
1

Если вы не хотите использовать pandas read_html, вы можете проанализировать его более сложно:

import pandas as pd 
from bs4 import BeautifulSoup 

table = BeautifulSoup(open('test.html','r').read()) 

#generate header from first tr 
h = [[td.span.get('id') for td in row.select('td') if td.span != None ] 
      for row in table.findAll('tr')] 
#remove empty lists 
h = [x for x in h if x != []]    
header = h[0] 
print header 
['Grid_exdate_43', 'Grid_CashAmount_43', 'Grid_DeclDate_43', 'Grid_RecDate_43', 'Grid_PayDate_43'] 

#if generating header is problematic, you can specify them 
#header = ['Grid_exdate', 'Grid_CashAmount', 'Grid_DeclDate', 'Grid_RecDate', 'Grid_PayDate' ] 

#get content of table, remove td with text Cash 
body = [[td.text.strip() for td in row.select('td') if td.text.strip() != 'Cash'] 
      for row in table.findAll('tr')] 
#remove empty lists 
body = [x for x in body if x != []]     

cols = zip(*body) 

tbl_d = {name:col for name, col in zip(header,cols)} 

df = pd.DataFrame(tbl_d, columns = header) 
print df 
    Grid_exdate_43 Grid_CashAmount_43 Grid_DeclDate_43 Grid_RecDate_43 \ 
0  2/15/2005    0.08    --  2/17/2005 
1  11/15/2004    3.08    --  11/17/2004 

    Grid_PayDate_43 
0  3/10/2005 
1  12/2/2004 

#remove last 3 chars of column name 
#more rename info: 
#http://stackoverflow.com/questions/11346283/renaming-columns-in-pandas 
df.rename(columns=lambda x: x[:-3], inplace=True) 
#convert columns to datetime columns 
df['Grid_exdate'] = pd.to_datetime(df['Grid_exdate']) 
df['Grid_RecDate'] = pd.to_datetime(df['Grid_RecDate']) 
df['Grid_PayDate'] = pd.to_datetime(df['Grid_PayDate']) 

print df 

    Grid_exdate Grid_CashAmount Grid_DeclDate Grid_RecDate Grid_PayDate 
0 2005-02-15   0.08   -- 2005-02-17 2005-03-10 
1 2004-11-15   3.08   -- 2004-11-17 2004-12-02 
Смежные вопросы