BeautifulSoup for循环 - 结合每两个循环的结果

时间:2018-03-05 10:47:18

标签: python beautifulsoup

我正在尝试使用具有以下结构的HashMap来解析HTML:

beautifulSoup

我遇到的问题是我想将标题添加到数据框的同一行作为数据。但是使用for循环(基于查找表)我不知道如何将标题与数据点放在同一个列表中 - 这样进入数据框的数据就是[ <table> <tr><td class="title">Title 2</td></tr> </table> <table> <tr><td>Label 1</td><td>Label 2</td><td>Label 3</td></tr> <tr><td class="data">Data 1</td><td class="data">Data 2</td><td class="data">Data33</td></tr> </table> <table> <tr><td class="title">Title 2</td></tr> </table> <table> <tr><td>Label 1</td><td>Label 2</td><td>Label 3</td></tr> <tr><td class="data">Data 1</td><td class="data">Data 2</td><td class="data">Data33</td></tr> </table> ] < / p>

python代码是:

title, Data 1, Data 2, Data 3

我已经尝试将其包装在另一个for循环中,但由于需要遍历表格,因此无效。

我可以创建两个数据框(一个用于标题,一个用于数据),然后在最后合并它们,但如果这是最好的方法,我会感到惊讶。

有谁知道如何合并两个for循环的集合结果(即tables = soup.find_all('table') i = 0 for t in tables: if(i % 2) == 1: datapoints = t.find_all('td', class_='data') data = [] for d in datapoints: data.append(d.text) i += 1 else: title = t.find('td', class_='title').text i += 1 )?

2 个答案:

答案 0 :(得分:0)

如何使用try..except

for table in soup.find_all('table'):
    try:
        title = table.find('td', class_='title').text
    except AttributeError:    # Triggers if no title present
        data = [td.text for td in table.find_all('td', class_='data')]

获取所需的列表:

data = []
for table in soup.find_all('table'):
    try:
        data.append([table.find('td', class_='title').text])
    except AttributeError:    # Triggers if no title present
        data[-1].extend(td.text for td in table.find_all('td', class_='data'))
print(data)
# [['Title 1', 'Data 1', 'Data 2', 'Data33'],
#  ['Title 2', 'Data 1', 'Data 2', 'Data33']]

只要标题后面紧跟着包含相应数据的表格,就可以正常工作。

但是,如果您想在之后将其添加到pandas.DataFrame,这可能更容易:

import pandas as pd

titles, data = [], []
for table in soup.find_all('table'):
    try:
        titles.append(table.find('td', class_='title').text)
    except AttributeError:    # Triggers if no title present
        data.append([td.text for td in table.find_all('td', class_='data')])
df = pd.DataFrame(zip(*data), columns=titles)
# df = pd.DataFrame.from_items(zip(titles, data))  # also works
print(df)
#   Title 1 Title 2
# 0  Data 1  Data 1
# 1  Data 2  Data 2
# 2  Data33  Data33

答案 1 :(得分:0)

一些意见:

  • 为了更好的可读性,您可以在主enumerate循环
  • 中使用for
  • 如果我没有误解你,你已经考虑使用字典,但你更喜欢使用2D数组。
  • 您可以使用zip()进行合并

    titles = [t.find('td', class_='title').text for idx,t in enumerate(tables) if idx % 2 == 0]
    
    datas = [[td.text for td in table.find_all('td', class_='data')] for idx,t in enumerate(tables) if idx % 2 != 0 ]
    
    structured = zip(titles,datas)