搜索目标文件以查找保存在 .txt 或 .csv 中的术语并重新查找?

问题描述 投票:0回答:1

对 python 和编码来说相对较新,但我想我已经把头撞在墙上了,足以应对这个问题了。我来 Stack Overflow 寻求明智的建议。

我正在编写一个程序,它将在目标文件夹中搜索存储在“keyterms.csv”中的预定义术语。 keyterms.csv 有一列由换行符分隔的单词和短语,没有其他内容。当在目标目录中的文件中找到关键字术语文件中的单词或短语时,程序会返回罪魁祸首文件的名称以及找到的关键字术语的条目数。

Traceback (most recent call last):
count = len(re.findall(self.ktxt, ttxt))
TypeError: unhashable type: 'dict'

所以我认为答案很明显,re.findall 只适用于字符串或仅输出字符串的东西,而不适用于字典、列表或其他类似的东西。我尝试了 SO 中的几个代码片段,将读取的文件分割成单独的字符串以输入 re.findall,但无济于事。我应该将字符串输入到数组或其他东西中,然后 for.each 数组吗?不知道我到底错过了什么。

无视我大量的打印语句,只是用它们来追踪正在发生的事情。

据我所知,

def read_key
def find
是问题所在。我尝试过以多种方式拆分
self.ktxt = list(reader)
介绍字符串并将其发送到
def find
,但也许我根本不明白它是怎么回事。

import os
import re
import csv


class FindKterms:

    def __init__(self, path, query):
        self.path = path
        self.query = query
        self.ktxt = {}
        self.searched = {}
        print('def init complete ...')

    def read_key(self):
        print('opening keyterms.csv')
        with open(self.query, newline='', encoding='utf_8') as f:
            reader = csv.reader(f, delimiter='\n')
            self.ktxt = list(reader)

    def find(self):
        if self.path[-1] != '/':
            self.path += '/'
            print('Appended "/" to given filepath')
        print('starting find function ...')
        for root, dirs, files in os.walk(self.path):
            for file in files:
                print('Searching: ' + file + ' ...')
                f = open(root + file)
                ttxt = f.read()
                f.close()
                print('successfully read and closed ' + file)

                count = len(re.findall(self.ktxt, ttxt))
                if count > 0:
                    self.searched[root + file] = count

    def get_results(self):
        return self.searched

main()
似乎可以很好地调用函数并移动数据。正在调用函数并且似乎可以正常工作。只需将 keyterms.csv 中的字符串用作目标目录中 re.findall 的匹配案例即可。

感谢您的任何帮助,我觉得我就在那里,但解决方案却让我困惑。

python csv
1个回答
0
投票

虽然 keyterms.csv 具有 .csv 扩展名,但没有理由将其视为 CSV 文件,因为它每行只有一个单词(术语)。因此,您可以打开它,一次读取一行并构建您的查询(正则表达式)。

假设我们有如下所示的 keyterms.csv:

ghi
xyz
abc

然后,在名为 data 的目录中,我们有 3 个文件 - a.txt、b.txt 和 c.txt,其内容如下:

ghi
ghi
abc
zzz

ghi
abc
abc
zzz

ppp

现在课程可以如下:

import re
from pathlib import Path
from collections import Counter

class FindKterms:
    def __init__(self, path: Path, query: Path):
        self._path = path # directory to be searched
        self._query = query # file containing list of terms to be searched for
        assert self._path.exists() and self._path.is_dir()
        assert self._query.exists() and self._query.is_file()
    @property
    def terms(self) -> re.Pattern:
        if not hasattr(self, "_terms"):
            with self.query.open() as q:
                qt = {line.strip() for line in q}
                self._terms = re.compile("(" + "|".join(qt) + ")")
        return self._terms
    @property
    def path(self) -> Path:
        return self._path
    @property
    def query(self) -> Path:
        return self._query
    def process(self) -> dict[str, Counter]:
        result = {}
        for file in self.path.glob("*"):
            with file.open() as fd:
                if f := self.terms.findall(fd.read()):
                    result[file.name] = Counter(f)
        return result

path = Path("~/data").expanduser()
query = Path("~/keyterms.csv").expanduser()

print(FindKterms(path, query).process())

输出:

{'b.txt': Counter({'abc': 2, 'ghi': 1}), 'a.txt': Counter({'ghi': 2, 'abc': 1})}

因此我们可以看到b.txt有2个'abc'和1个'ghi',a.txt有2个'ghi'和1个'abc'。文件 c.txt 确实出现在输出中,因为它不包含任何关键术语

© www.soinside.com 2019 - 2024. All rights reserved.