python - 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 中这样做。
先感谢您!
解决方案
您的 details
列表嵌套的原因是因为您正在以这种方式构建它;也就是说,如果您append
将list
( 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)
发布输出有点太笨拙了。而且您可能仍然想要进行格式化,但这超出了您原始帖子的范围。希望这里有帮助!
推荐阅读
- laravel - Laravel Dusk - 如何从 bootstrap-vue 组件中选择多个复选框
在测试中 - vb.net - 如何将 e_sqlcipher 与 microsoft.data.sqlite 一起使用?
- javascript - 在 Discord.js 13 中单击按钮后如何禁用按钮
- ignite - 从 apache ignite 2.7.0 迁移到 2.10.0
- javascript - 上下文更新时调用函数 React
- delphi - 我有一个德尔福作业。如果我在编辑框中输入文本并且少于 6 个字母,则不允许使用,如果是则有效
- java - Gmail Api 请求的身份验证范围不足
- python - 调用循环 html jinja 无法调用表格 HTML 上的某些图像
- visual-studio-code - 在 yaml 自动格式化程序中保持矩阵的形状
- ios - ld:架构 x86_64 的 7 个重复符号 clang:错误:链接器命令失败,退出代码 1 反应原生 ios 应用程序构建失败