代码之家  ›  专栏  ›  技术社区  ›  Todd Burus

为什么csv会在标题后得到空白行?

  •  0
  • Todd Burus  · 技术社区  · 6 年前

    我正在使用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()函数,但没有成功。

    谢谢。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Bailey Parker    6 年前

    在我看来这是来自:

    [[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>
    

    请注意,从中获取标题的行是 <tr> 前面紧接着 <tr> (这与 tr + tr )中。但是因为它没有 <td> 在里面,这个列表理解是空的: [td.text for td in row.find_all("td")] 是的。

    我建议采用以下方法,而不是这种方法:

    1. 收集所有 <tr> 表中的S: rows = table.select('tr')
    2. 从列表顶部移除行,直到找到标题(一个带有多个 <th> (第页)
    3. 然后,现在头已经被剥离,您可以使用对其余行的列表理解来提取数据: [[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')]