python - 为什么 CSV 在标题后出现空白行?
问题描述
我正在使用 BeautifulSoup 从网站上抓取表格,但我很困惑为什么在我的标题之后打印一个空白行以及如何修复它。
我的代码是:
page = requests.get('http://racing-reference.info/loopdata/2018-18/W')
page.encoding = 'utf-8'
soup = BeautifulSoup(page.text, 'html.parser')
table = soup.find_all(class_ = 'tb')
headers = [th.text for th in table[2].select("tr th")]
with open("out.csv", "w", newline='') as f:
wr = csv.writer(f)
wr.writerow(headers)
wr.writerows([[td.text
for td in row.find_all("td")]
for row in table[2].select("tr + tr")])
正在读取的 HTML 如下所示:
<BR><BR><TABLE class=tb WIDTH=100% CELLPADDING=3 CELLSPACING=0>
<TR><TD ALIGN=CENTER COLSPAN=19 class=col>
<TR><TD COLSPAN=19 HEIGHT=20 ALIGN=CENTER class=newhead>Loop data for this race:</TD></TR>
<TR><TH class=col><A HREF=/loopdata?s=1&series=W&id=2018-18>Driver</A></TH>
<TH class=col><A HREF=/loopdata?s=2&series=W&id=2018-18>Start</A></TH>
<TH class=col><A HREF=/loopdata?s=3&series=W&id=2018-18>Mid Race</A></TH>
<TH class=col><A HREF=/loopdata?s=4&series=W&id=2018-18>Finish</A></TH>
<TH class=col><A HREF=/loopdata?s=5&series=W&id=2018-18>High Pos.</A></TH>
<TH class=col><A HREF=/loopdata?s=6&series=W&id=2018-18>Low Pos.</A></TH>
<TH class=col><A HREF=/loopdata?s=7&series=W&id=2018-18>Avg. Pos.</A></TH>
<TH class=col><A HREF=/loopdata?s=8&series=W&id=2018-18>Pass Diff.</A></TH>
<TH class=col><A HREF=/loopdata?s=9&series=W&id=2018-18>Green Flag Passes</A></TH>
<TH class=col><A HREF=/loopdata?s=10&series=W&id=2018-18>Green Flag Times Passed</A></TH>
<TH class=col><A HREF=/loopdata?s=11&series=W&id=2018-18>Quality Passes</A></TH>
<TH class=col><A HREF=/loopdata?s=12&series=W&id=2018-18>Pct. Quality Passes</A></TH>
<TH class=col><A HREF=/loopdata?s=13&series=W&id=2018-18>Fastest Lap</A></TH>
<TH class=col><A HREF=/loopdata?s=14&series=W&id=2018-18>Top 15 Laps</A></TH>
<TH class=col><A HREF=/loopdata?s=15&series=W&id=2018-18>Pct. Top 15 Laps</A></TH>
<TH class=col><A HREF=/loopdata?s=16&series=W&id=2018-18>Laps Led</A></TH>
<TH class=col><A HREF=/loopdata?s=17&series=W&id=2018-18>Pct. Laps Led</A></TH>
<TH class=col><A HREF=/loopdata?s=18&series=W&id=2018-18>Total Laps</A></TH>
<TH class=col><A HREF=/loopdata?s=19&series=W&id=2018-18>DRIVER RATING</A></TH>
</TR>
<TR CLASS=odd><TD class=col NOWRAP><A HREF=/driverlog/joneser02/W/2018 title="View this driver's loop data for all races">Erik Jones</A></TD><TD class=col ALIGN=RIGHT>29</TD><TD class=col ALIGN=RIGHT>26</TD><TD class=col ALIGN=RIGHT>1</TD><TD class=col ALIGN=RIGHT>1</TD><TD class=col ALIGN=RIGHT>31</TD><TD class=col ALIGN=RIGHT>18</TD><TD class=col ALIGN=RIGHT>31</TD><TD class=col ALIGN=RIGHT>153</TD><TD class=col ALIGN=RIGHT>122</TD><TD class=col ALIGN=RIGHT>46</TD><TD class=col ALIGN=RIGHT>30.1</TD><TD class=col ALIGN=RIGHT>9</TD><TD class=col ALIGN=RIGHT>49</TD><TD class=col ALIGN=RIGHT>29.2</TD><TD class=col ALIGN=RIGHT>1</TD><TD class=col ALIGN=RIGHT>0.6</TD><TD class=col ALIGN=RIGHT>168</TD><TD class=col ALIGN=RIGHT>84.6</TD></TR>
标题和数据打印得很好,但是标题和数据之间有一个我似乎无法摆脱的空白行。我试过在行上使用 any() 函数,但这不起作用。
谢谢。
解决方案
在我看来,这来自:
[[td.text for td in row.find_all("td")] for row in table[2].select("tr + tr") if row]
如果我们查看您的 HTML,它具有以下一般形式:
<table>
<tr><td></td></tr>
<tr><td></td></tr>
<!-- note this tr has no tds -->
<tr><th></th><!-- ... --></tr>
<tr><td></td><!-- ... --></tr>
请注意,您从中获取标题的行是 a<tr>
前面紧跟 a <tr>
(这匹配tr + tr
)。但是由于它里面没有任何<td>
s,所以这个列表推导是空的:[td.text for td in row.find_all("td")]
。
我建议使用以下方法,而不是这种方法:
<tr>
将表中的所有 s收集起来:rows = table.select('tr')
- 从该列表的顶部删除行,直到找到标题(一个带有多个
<th>
s) - 然后,既然标题已被剥离,您可以对剩余的行使用列表理解来提取数据:
[[td.text for td in row] for row in rows]
或者,如果您不需要对数据进行任何处理(而只想将其直接转换为 CSV),您可以只执行一个列表推导并提取<th>
s 或<td>
s.
[[x.text for x in row.find_all('td, th')] for row in table.select('tr')]
推荐阅读
- python - 具有可变数量参数的 f 字符串?
- oracle - 我可以在 Xquery 中使用用户定义的函数来替换 PLSQL 中的节点值吗?
- excel - 如何在VBA中用0替换数组中的黑色值
- python - Pyomo 中的双变量不返回任何内容
- typescript - 地理编码没有等待承诺
- xcode - Xcode 12.0.1 - 没有可下载的模拟器
- java - 错误:使用 --enable-preview 的无效源版本 14
- html - 阻止表格单元格内容包裹在内部元素上
- json - 如何通过GCS将GA360表从Big query导出到雪花作为json文件而不丢失数据?
- python - 熊猫雕刻绳子的某个部分