Python靓汤汇排

2024-04-25 08:29:51 发布

您现在位置:Python中文网/ 问答频道 /正文

这是html

<table>
<tr>
<td class="break">mono</td>
</tr>
<tr>
<td>c1</td>
<td>c2</td>
<td>c3</td>
</tr>
<tr>
<td>c11</td>
<td>c22</td>
<td>c33</td>
</tr>
<tr>
<td class="break">dono</td>
</tr>
<tr>
<td>d1</td>
<td>d2</td>
<td>d3</td>
</tr>
<tr>
<td>d11</td>
<td>d22</td>
<td>d33</td>
</tr>
</table>

现在我想在csv文件中输出如下:

^{pr2}$

但我得到的输出是这样的:

mono
c1 c2 c3
c11 c22 c33
dono
d1 d2 d3
d11 d22 d33

这是我的代码:

import codecs
from bs4 import BeautifulSoup
with codecs.open('dump.csv', "w", encoding="utf-8") as csvfile:


    f = open("input.html","r")

    soup = BeautifulSoup(f)
    t = soup.findAll('table')
    for table in t:
        rows = table.findAll('tr')
        for tr in rows:
            cols = tr.findAll('td')
            for td in cols:
                csvfile.write(str(td.find(text=True)))
                csvfile.write(",")
            csvfile.write("\n")

请帮我解决这个问题问题。谢谢. 在

编辑:

再解释一下详细信息。这里我需要添加第一节(mono,dono等)将被附加。在

这里的规则是,除非我遇到一个新的“break”类,否则该类中的文本应该附加到该类下面的任何tr中。在


Tags: csvfileinforhtmltabletrclasswrite
3条回答

既然你的新问题实际上是一个与原始问题完全不同的问题,这里有一个完全不同的答案:

for table in t:
    rows = table.findAll('tr')
    for row in rows:
        cols = row.findAll('td')
        if 'break' in cols[0].get('class', []):
            header = cols[0].text
        else:
            print header, ' '.join(col.text for col in cols)

我假设一行要么正好是1个“break”列,要么是1个或多个常规列。如果这些假设不成立,可以修改代码。在

另外,如果join函数中的生成器表达式使您感到困惑,那么可以将相同的内容重写为显式循环:打印标题;然后为每个列打印该列;然后打印换行符。在

既然你要求解释'break' in cols[0].get('class', []),我就把它分解。在

  • cols是当前tr节点中每个td节点的BS4Tag对象的list。在
  • cols[0]是第一个。在
  • cols[0].get('class', [])Tag对象视为字典,如the docs所述,并对其调用熟悉的get(key, defaultvalue)方法。
    • 在BS4中(与旧版本不同),按名称查找Tag属性总是返回list。BS3将为<td class='foo bar'>返回'foo bar',为<td class='foo' class='bar'>返回{},而BS4将为两者返回['foo', 'bar']。在
  • 把它们放在一起,cols[0].get('class', [])对于<td class='break'>的情况是['break'],对于示例输入中的所有其他情况,[]。在

如上所述,我假设一行要么正好是1个“break”列,要么是1个或多个常规列。你可以看到我在代码中使用这些假设的地方。但如果这些假设被打破,你还没有告诉我们足够多的信息来知道你在这些情况下想要做什么。在

如果有没有列的行,显然cols[0]将引发一个IndexError。但你必须决定在这种情况下该怎么做。它应该什么都不做吗?只打印页眉?更改为在我们看到标题行之前不打印任何内容的状态?不管你怎么决定,编码都应该很容易。在

如果有任何行的标题后跟普通行,则将忽略普通行。如果有任何不是行中第一列的标题,它们将被视为普通值。如果在同一行中有多个标题,则将忽略除第一个外的所有标题。等等。在每种情况下,这可能是什么,也可能不是什么。但是在你能写代码之前,你必须决定你想要什么。在

使用内置的csv模块处理CSV文件。这比手动操作要容易得多。在

至于您的问题,这是因为您的csvfile.write('\n')缩进太多,所以数据的写入方式与表中显示的一样。做一个发电机,它应该可以工作:

import csv
from bs4 import BeautifulSoup

def get_fields(soup):
    for td in soup.find_all('td'):
        yield td.get_text().strip()

with open('csvfile.csv', 'w') as csvfile:
    writer = csv.writer(csvfile)

    with open('input.html', 'r') as handle:
        soup = BeautifulSoup(handle.read())

    fields = list(get_fields(soup))

    writer.writerow(fields)

您是否尝试过取消缩进csvfile.write("\n"),以便它出现在表循环的末尾,而不是tr循环的末尾?在

相关问题 更多 >