2017-01-09 58 views
1

我有一組需要與100K輸入文件匹配的400K關鍵字集。從大型存儲庫到文件的關鍵字匹配

我現在的做法如下。

代碼:

import glob 
with open("keyword.txt") as inp: 
    keyword_set=set([lin.strip().lower() for lin in inp]) 
for fil in glob.glob("file/path/*.txt"): 
    with open(fil) as inp, open("output.txt","w") as out: 
     file_txt = inp.read().lower() 
     for val in keyword_set: 
      if val in file_txt: 
       out.write("{}\t{}".format(fil, val)) 

Keyword_Sample:

BUENOS AIRES 
Argentina 

因爲我遍歷一個大的庫需要花費大量的時間(從幾秒變化到分鐘的文件。 )。 有沒有什麼辦法可以增加通過量並減少所需的時間。

+0

猜你的例子中只有1個匹配的每個實例?如果是的話,那麼在'out.write'之後的新行上添加'break'在相同的縮進級別 –

+0

@Chris_Rands否,那不是我爲單個文件有多個關鍵字匹配的情況。我只是將它們分別寫入下行流程 –

回答

1

看你的代碼:

file_txt = inp.read().lower() 
    for val in keyword_set: 
     if val in file_txt: 
      out.write("{}\t{}".format(fil, val)) 

聲明

 if val in file_txt: 

會在文本字符串(字符串搜索,時間複雜度不超過O(N * C)在平均情況較少) 。如果你的文字由單詞組成(如你的例子),你可以使用更合適的表達。

例如,將file_txt中的所有單詞表示爲set()(與第二組一樣)。如果可能的話,當然可以用分隔符分割文件中的文本。如果關鍵字可以包含2個或更多的單詞,則必須添加到您設置的順序對(bigrams)和三元組(trigrams)。之後你可以在集合中搜索關鍵字,這個語句的時間複雜度等於平均情況下的O(1)。

import glob 
with open("keyword.txt") as inp: 
    keyword_set=set([lin.strip().lower() for lin in inp]) 
for fil in glob.glob("file/path/*.txt"): 
    with open(fil) as inp, open("output.txt","w") as out: 
     file_txt = inp.read().lower() 
     file_set = set(file_txt.split('Your delimiter')) 
     # [ adding bigrams (or trigrams) to the set ] 
     for val in keyword_set: 
      if val in file_set: 
       out.write("{}\t{}".format(fil, val)) 

     # [You can use set intersection operation here instead of cycle] 

如果要考慮到出現次數的計數帳戶,你必須使用collections.Counter,而不是set

+0

因此,您所說的是將文本轉換爲集合並查找。如果我有像10個單詞這樣的大關鍵字,那麼我必須使用文件內容創建一組10,然後查看。 –

+0

@Pythonmaster,在'set/Counter'中添加順序字是個好主意。如果你的代碼是緩慢的部分是子串搜索程序。如果您的表現更好,您將獲得最佳表現。 – Dmitry

+0

感謝隊友你的想法確實有道理 –