使用Python将纯文本文件解析成CSV文件

6

我有一系列HTML文件,使用Beautiful Soup将它们解析成一个文本文件。这些HTML文件的格式使得它们在文本文件中的输出总是三行,因此输出看起来会像是:

Hello!
How are you?
Well, Bye!

但同样也有可能是这样的。
83957
And I ain't coming back!
hgu39hgd

换句话说,HTML文件的内容在各自之间并不完全标准化,但它们总是会产生三行内容。
因此,我想知道如果我想要将Beautiful Soup生成的文本文件解析成带有列的CSV文件(使用上述示例),我应该从哪里开始。
Title   Intro   Tagline
Hello!    How are you?    Well, Bye!
83957    And I ain't coming back!    hgu39hgd

从文本文件中去除HTML的Python代码如下:

import os
import glob
import codecs
import csv
from bs4 import BeautifulSoup

path = "c:\\users\\me\\downloads\\"

for infile in glob.glob(os.path.join(path, "*.html")):
    markup = (infile)
    soup = BeautifulSoup(codecs.open(markup, "r", "utf-8").read())
    with open("extracted.txt", "a") as myfile:
        myfile.write(soup.get_text())

我了解到我可以使用这个来设置CSV文件中的列:

csv.put_HasColumnNames(True)

csv.SetColumnName(0,"title")
csv.SetColumnName(1,"intro")
csv.SetColumnName(2,"tagline")

我不太清楚的是如何一次只读取文本文件(extracted.txt)中的一行,并在到达新行时将其设置为CSV文件中的正确单元格。 文件的前几行为空白行,在每个文本分组之间有许多空白行。因此,首先需要打开文件并读取它:

file = open("extracted.txt")

for line in file.xreadlines():
    pass # csv.SetCell(0,0 X) (obviously, I don't know what to put in X)

此外,我不知道如何告诉Python继续读取文件并将其添加到CSV文件中,直到完成为止。换句话说,在HTML文件中没有办法准确知道有多少行,所以我不能只使用csv.SetCell(0,0)到cdv.SetCell(999,999)来完成。

1
现在已经没有人再使用.xreadlines了,而是使用for line in file - jamylak
我不确定我理解你想做什么。你是想读取 extracted.txt 文件,忽略空行,并将每个三行组成的组合放到 CSV 文件的一行中吗? - icktoofay
差不多了。我正在尝试读取三行中的第一行并将其设置为“标题”,读取三行中的第二行并将其设置为“简介”,读取三行中的第三行并将其设置为“标语”,然后跳过空格,直到我到达下一个三行,然后再次执行相同操作。 - user1183556
此外,在文件的最顶端和第一个“title”之间有空格。 - user1183556
我在考虑使用fileIN = open(sys.argv[1], "r")和line = fileIN.readline()。但我不知道如何跳过空格,或者得到文本后该怎么处理? - user1183556
@ZacBrown 请检查我的答案并告诉我是否理解正确。 - Oscar Mederos
2个回答

6

我不确定您使用的是哪个CSV库,但它似乎不是Python内置的CSV库。无论如何,以下是我的做法:

import csv
import itertools

with open('extracted.txt', 'r') as in_file:
    stripped = (line.strip() for line in in_file)
    lines = (line for line in stripped if line)
    grouped = itertools.izip(*[lines] * 3)
    with open('extracted.csv', 'w') as out_file:
        writer = csv.writer(out_file)
        writer.writerow(('title', 'intro', 'tagline'))
        writer.writerows(grouped)

这可以形成一个流水线。首先从文件中获取数据,然后删除所有行的空格,接着删除任何空行,然后将它们分组为三个一组,最后在写入CSV头部后,将这些分组写入CSV文件。
如你在评论中提到的合并最后两列,你可以以明显的方式更改writerow呼叫,把writerows更改为:
writer.writerows((title, intro + tagline) for title, intro, tagline in grouped)

1
在我看来,我认为生成器更清晰(就像您在编辑之前的那样)。 - Oscar Mederos
1
@OscarMederos:它有一个bug:在分组之前它没有去掉换行符。尽管如此,我想我可以再次用生成器推导来重写它。 - icktoofay
哦,非常抱歉我应该在帖子中解释一下。另外,这段代码在MacOSX自带的Python(2.7.2)中完美运行。 - user1183556
你有没有关于如何将第2行和第3行合并成一列的指针呢? :-) - user1183556
如果我的文本文件中有这样的内容SumFunction : 0.2,我想要SumFunction在第一列,0.2在第二列,该怎么办? - Lily
显示剩余4条评论

2
也许我理解有误,但您可以这样做:
file = open("extracted.txt")

# if you don't want to do .strip() again, just create a list of the stripped 
# lines first.
lines = [line.strip() for line in file if line.strip()]

for i, line in enumerate(lines):
    csv.SetCell(i % 3, line)

这个很接近,但是@icktoofay得到了正确答案。不过还是谢谢你的帮助! - user1183556
@ZacBrown 你所说的“相当接近”是什么意思?你试过了吗?我刚刚尝试着让它与你尝试的方式尽可能相似(使用csv.SetCell等)。顺便说一句,我已经为他的答案点赞了 ;) - Oscar Mederos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接