首页 > 解决方案 > BeautifulSoup:重复列

问题描述

我正在尝试从包含表格的网页中抓取数据,然后将其放入熊猫数据框中。

我相信一切都做对了,但我得到了重复的列......

这是我的代码:

html_content = requests.get('http://timetables.itsligo.ie:81/reporting/individual;student+set;id;SG_KAPPL_H08%2FF%2FY1%2F1%2F%28A%29%0D%0A?t=student+set+individual&days=1-5&weeks=29&periods=3-20&template=student+set+individual').text


soup = BeautifulSoup(html_content,'html.parser')

all_tables = soup.find_all('table')

wanted_table = all_tables[6]

first_tr = wanted_table.find('tr')

following_tr = first_tr.find_next_siblings()


details = []

for tr in following_tr:
    prepare = []
    for td in tr.find_all('td'):
        prepare.append(td.text)
    details.append(prepare)

df = pd.DataFrame(details)
pd.set_option('display.max_columns', None)
display(df)

效果很好,但正如您在下面的图片(第 0 行中的第 1 列和第 2 列)中看到的那样,我得到重复的 td 并且一个总是重复 \n。

我注意到的事情是,由于某种原因,详细信息列表返回了它的两倍,也许有一个表嵌套在一个表中?

顺便说一句,我在 jupyter 中这样做。

先感谢您!

标签: pythonhtmlpandasweb-scrapingbeautifulsoup

解决方案


您的 details列表嵌套的原因是因为您正在以这种方式构建它;也就是说,如果您appendlist( prepare) 转换为另一个list( details),则会得到一个嵌套的list. 见这里。这没关系,因为它可以很好地读入您的 DataFrame。

不过,您是正确的,HTML 中有一个嵌套表的事情。我不会尝试在此处格式化 HTML,但日程表中的每个框都在<td>总体wanted_table. 当其中一个单元中有一个课程时,另一个<table>用于保存细节。所以类名、教授等是<td>这个嵌套的更多元素<table>。因此,在查找所有单元格 ( tr.find_all('td')) 时,您会遇到较大的类框及其嵌套元素。当你得到.text最外层的时候<td>,你也会从最里面的单元格中得到文本,因此是重复的。

我不确定这是否是最好的方法,但一种选择是防止搜索进入嵌套表,recursive使用find_all.

# all your other code above

for tr in following_tr:
    prepare = []
    for td in tr.find_all('td', recursive=False):
        prepare.append(td.text)
    details.append(prepare)

df = pd.DataFrame(details)

以上应防止出现重复的元素。但是,仍然存在\n字符多的问题,并且不包括某些单元格跨越多个列的事实。strip您可以通过在文本中添加一些 -ing来开始修复第一个问题。第二,您可以访问colspan属性来填充prepare列表:

# all your other code above

for tr in following_tr:
    prepare = []
    for td in tr.find_all('td', recursive=False):
        text = td.text.strip('\s\n')
        prepare += [text] + [None] * (int(td.get('colspan', 0)) - 1)
    details.append(prepare)

df = pd.DataFrame(details)

发布输出有点太笨拙了。而且您可能仍然想要进行格式化,但这超出了您原始帖子的范围。希望这里有帮助!


推荐阅读