1

我有一个 .txt 文件,其中包含我研究所需的大量文本信息。因此,我正在尝试编写一个执行关键字搜索的程序(在我的情况下,我需要短语“sold salt”),然后它将以该短语开头的文本逐行写入一个新文件并剪切在某个时候关闭(我还没有决定)。它实际上是一本书,其中包含 17 世纪的数字化文档,用古俄语写成,但示意性的文本如下所示:

“表_№1

文字文字文字文字

文字 文字

文本 文本 文本 文本 文本 文本出售 盐文本 文本 文本 文本出售 盐文本 文本 文本 文本 文本 文本 文本

文字文字文字文字

sheet_№1_reverse

文本文本出售盐文本文本文本文本文本文本文本文本文本文本文本文本文本文本"

所以这是一件非常糟糕的结构化事情,我想要的是将所有盐销售记录及其在整个文本中的位置放在一个文件中以供我研究。

现在,很抱歉介绍了很长时间,我只是想展示我必须处理的内容。

我尝试使用 docx lib 编写代码,但事实证明,它可以解决的唯一方法是,如果我在 docx 文件中强调需要的信息,而不是使用代码将其取出,这并不是很糟糕,但它仍然需要时间。

所以我以 txt 格式停止,现在我得到了这个:

key_1 = 'sold'
key_2 = 'salt'

f_old = open("text.txt", encoding='utf-8')
f_result = open("text_result.txt", 'w', encoding='utf-8')

for line in f_old:
    line = line.split()
    if len(line) == 1:
        for elem in range(len(line)):
            f_result.write(line[elem] + '\n')
    else:
        if key_1 in line and key_2 in line:
            for word in range(len(line)):
                if line[word] == key_1 and line[word + 1] == key_2:
                    for elem in line[word: word + 10]:
                        f_result.write(elem + ' ')
                    f_result.write('\n')

f_old.close()
f_result.close()

基于上面的例子,它给了我这个结果:

“表_№1

出售盐文本文本文本文本文本出售盐文本

卖盐文字 文字 文字 文字 文字 文字

sheet_№1_reverse

卖盐文字文字文字文字文字文字文字文字文字”

将“已售盐”和其他额外信息(例如第二行末尾的信息)用我的手切掉并不是什么大不了的事,因为无论如何我都会使用包含比我需要的更多信息的行来执行此操作。但是,如果我的关键字出现在该行中两次或更多次,是否有任何想法如何减少行?

我有一个想法,打开 text_result 不仅是为了写作,而且是为了阅读,然后通过以下方式剪断这些行:

for line in f_result:
    line = line.split()
    if len(line) > 1:
        for word in line[::-1]:
            while line[word] != key_1:
                line.pop([word])

但如果我把它放在这样的代码中,它就不起作用:

key_1 = 'sold'
key_2 = 'salt'
f_old = open("text.txt", encoding='utf-8')
f_result = open("text_result.txt", 'w+', encoding='utf-8')

for line in f_old:
    line = line.split()
    if len(line) == 1:
        for elem in range(len(line)):
            f_result.write(line[elem] + '\n')
    else:
        if key_1 in line and key_2 in line:
            for word in range(len(line)):
                if line[word] == key_1 and line[word + 1] == key_2:
                    for elem in line[word: word + 7]:
                        f_result.write(elem + ' ')
                    f_result.write('\n')

for line in f_result:
    line = line.split()
    if len(line) > 1:
        for word in line[::-1]:
            while line[word] != key_1:
                line.pop([word])

f_old.close()
f_result.close()

我只是缺少一些基本的东西吗?

提前致谢!!!

4

1 回答 1

2

So based on the information you have provided, I supose you want to stop writing when you see another sold salt and then continue writing from there. This means that while writing you just need to make another check (like the one you already do) that the words that are going to the new file are not sold salt, and if they are, break out of there. It would look like this:

for line in f_old:
    line_words = line.split()  # it is confusing changing the value of a variable within the
    # loop, so I would recommend simply creating a new variable
    if len(line_words) == 1:
        # there was no need for a for loop here as we already know that there is only one element
        f_result.write(line_words[0] + '\n')
    else:
        for word in range(len(line_words)-1):  # as you will be accessing word+1 element,
        # you need to look out for out of range indices
            if line_words[word] == key_1 and line_words[word + 1] == key_2:
                for i in range(len(line_words[word: word + 10]))):
                    if i != 0 and line_words[word+i] == key_1 and line_words[word+i+1] == key_2:
                        break

                    f_result.write(line_words[word+i] + ' ')
                f_result.write('\n')


f_result.close()

I would also recommend using enumerate and then just using indices to access the element behind the one you need, I think it gives a cleaner code.

于 2020-10-25T15:29:50.790 回答