【原创】python倒排索引之查找包含某主题或单词的文件
什么是倒排索引?
倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。
假设我们现在有文件:
test1.txt中存有:我们爱自然语言处理
test2.txt中存有:我们爱计算机视觉
正向索引:{“test1.txt”:["我们",“爱”,"自然语言","处理"],"test2.txt":["我们","爱","计算机","视觉"]}
那么,我们应该如何通过正向索引找到包含某词语的文件呢?我们只能依次遍历文件中的内容,从内容中找到是否有该词语,正向查询的效率很低。
倒排索引:{"我们":["test1.txt","test2.txt"],"爱":["test1.txt","test2.txt"],"自然语言":["test1.txt"],"处理":["test1.txt"],"计算机":["test2.txt"],"视觉":["test2.txt"]}
建立倒排索引后,我们要想查找包含某些单词的文件,直接从hash表中获取,是不是就方便多了?接下来,我们用python实现:
现在有基本目录:
python.txt
Python的设计哲学是“优雅”、“明确”、“简单”。因此,Perl语言中“总是有多种方法来做同一件事”的理念在Python开发者中通常是难以忍受的。Python开发者的哲学是“用一种方法,最好是只有一种方法来做一件事”。在设计Python语言时,如果面临多种选择,Python开发者一般会拒绝花俏的语法,而选择明确的没有或者很少有歧义的语法。由于这种设计观念的差异,Python源代码通常被认为比Perl具备更好的可读性,并且能够支撑大规模的软件开发。这些准则被称为Python格言。在Python解释器内运行import this可以获得完整的列表。
Python开发人员尽量避开不成熟或者不重要的优化。一些针对非重要部位的加快运行速度的补丁通常不会被合并到Python内。所以很多人认为Python很慢。不过,根据二八定律,大多数程序对速度要求不高。在某些对运行速度要求很高的情况,Python设计师倾向于使用JIT技术,或者用使用C/C++语言改写这部分程序。可用的JIT技术是PyPy。
Python是完全面向对象的语言。函数、模块、数字、字符串都是对象。并且完全支持继承、重载、派生、多继承,有益于增强源代码的复用性。Python支持重载运算符和动态类型。相对于Lisp这种传统的函数式编程语言,Python对函数式设计只提供了有限的支持。有两个标准库(functools, itertools)提供了Haskell和Standard ML中久经考验的函数式程序设计工具。
java.txt
.简单性
Java看起来设计得很像C++,但是为了使语言小和容易熟悉,设计者们把C++语言中许多可用的特征去掉了,这些特征是一般程序员很少使用的。例如,Java不支持go to语句,代之以提供break和continue语句以及异常处理。Java还剔除了C++的操作符过载(overload)和多继承特征,并且不使用主文件,免去了预处理程序。因为Java没有结构,数组和串都是对象,所以不需要指针。Java能够自动处理对象的引用和间接引用,实现自动的无用单元收集,使用户不必为存储管理问题烦恼,能更多的时间和精力花在研发上。
.面向对象
Java是一个面向对象的语言。对程序员来说,这意味着要注意应中的数据和操纵数据的方法(method),而不是严格地用过程来思考。在一个面向对象的系统中,类(class)是数据和操作数据的方法的集合。数据和方法一起描述对象(object)的状态和行为。每一对象是其状态和行为的封装。类是按一定体系和层次安排的,使得子类可以从超类继承行为。在这个类层次体系中有一个根类,它是具有一般行为的类。Java程序是用类来组织的。
Java还包括一个类的扩展集合,分别组成各种程序包(Package),用户可以在自己的程序中使用。例如,Java提供产生图形用户接口部件的类(java.awt包),这里awt是抽象窗口工具集(abstract windowing toolkit)的缩写,处理输入输出的类(java.io包)和支持网络功能的类(java.net包)。
.分布性
Java设计成支持在网络上应用,它是分布式语言。Java既支持各种层次的网络连接,又以Socket类支持可靠的流(stream)网络连接,所以用户可以产生分布式的客户机和服务器。
网络变成软件应用的分布运载工具。Java程序只要编写一次,就可到处运行。
c.txt
C语言是一种结构化语言,它有着清晰的层次,可按照模块的方式对程序进行编写,十分有利于程序的调试,且c语言的处理和表现能力都非常的强大,依靠非常全面的运算符和多样的数据类型,可以轻易完成各种数据结构的构建,通过指针类型更可对内存直接寻址以及对硬件进行直接操作,因此既能够用于开发系统程序,也可用于开发应用软件。通过对C语言进行研究分析,总结出其主要特点如下:
()简洁的语言
C语言包含有各种控制语句仅有9种,关键字也只有32 个,程序的编写要求不严格且多以小写字母为主,对许多不必要的部分进行了精简。实际上,语句构成与硬件有关联的较少,且C语言本身不提供与硬件相关的输入输出、文件管理等功能,如需此类功能,需要通过配合编译系统所支持的各类库进行编程,故c语言拥有非常简洁的编译系统。 []
()具有结构化的控制语句
C语言是一种结构化的语言,提供的控制语句具有结构化特征,如for语句、if⋯else语句和switch语句等。可以用于实现函数的逻辑控制,方便面向过程的程序设计。 []
()丰富的数据类型
C语言包含的数据类型广泛,不仅包含有传统的字符型、整型、浮点型、数组类型等数据类型,还具有其他编程语言所不具备的数据类型,其中以指针类型数据使用最为灵活,可以通过编程对各种数据结构进行计算。 []
()丰富的运算符
C语言包含34个运算符,它将赋值、括号等均视作运算符来操作,使C程序的表达式类型和运算符类型均非常丰富。 []
()可对物理地址进行直接操作
C语言允许对硬件内存地址进行直接读写,以此可以实现汇编语言的主要功能,并可直接操作硬件。C语言不但具备高级语言所具有的良好特性,又包含了许多低级语言的优势,故在系统软件编程领域有着广泛的应用。 []
()代码具有较好的可移植性
C语言是面向过程的编程语言,用户只需要关注所被解决问题的本身,而不需要花费过多的精力去了解相关硬件,且针对不同的硬件环境,在用C语言实现相同功能时的代码基本一致,不需或仅需进行少量改动便可完成移植,这就意味着,对于一台计算机编写的C程序可以在另一台计算机上轻松地运行,从而极大的减少了程序移植的工作强度。 []
()可生成的高质量目标代码,高执行效率的程序
首先,我们导入相应的包:
#用于获取该目录下得所有txt文件,忽略掉文件夹及里面的
import glob
#主要是一些路径的操作
import os
#对句子进行分词或关键词提取
from jieba import analyse
接下来,我们要获取所有txt文件的绝对路径:
#获取当前pyhtho文件所在的目录:当前是:C:\gongoubo\python-work\direc\files
dir_path = os.path.dirname(os.path.abspath(__file__))
print(dir_path)
#存储txt文件的绝对路径为列表,同时为每个文件建立索引
def file_store():
files_name =[]
files_dict = {}
#获取file文件夹下所有为txt的文件
for i,name in enumerate(glob.glob("file/*.txt")):
files_dict[i] = name.split('\\')[-1]
file_name = dir_path + "\\" + name
files_name.append(file_name)
return files_name,files_dict
然后,我们读取每个txt文件,再对其进行关键词提取,将结果存储到新的txt中,并用原txt文件的索引命名:
#读取每个txt文件
def transform(files_name):
#注意打开的时候需要申明为utf-8编码
for i,j in enumerate(files_name):
#打开文件
tmp = open(j,'r',encoding='utf-8').read()
#提取关键词
content = analyse.extract_tags(tmp)
#也可以进行分词content=jieba.cut_for_search(tmp),关于jieba分词,可以看我的自然语言处理之基础技能
#新建process文件夹
path=dir_path+'\\file\\'+'process'
if not os.path.exists(path):
os.makedirs(path)
#为存储关键词的txt取名,对应这每个文件的索引
fp=open(path+'\\'+str(i)+'.txt','w',encoding='utf-8')
#将关键词写入到txt中
fp.write(" ".join(content))
fp.close()
运行后,我们会有如下目录:其中process文件夹下的是提取关键词后的结果,文件名对应索引,即{0:"c.txt",1:"java.txt",2:"python.txt"}
接下来,进行倒排索引的构建:
#建立倒排索引
def invert_index():
path=dir_path+'\\file\\'+'process'
word_dict = {}
# 取包含关键词的txt
for file in glob.glob(path+'/*.txt'):
#取出txt文件名,也就是文件的索引
index = file.split('\\')[-1][0]
#打开文件,并将关键词存储为列表
with open(file,'r',encoding='utf-8') as fp:
word_list=fp.read().split(" ")
#建立倒排索引,如果单词不在单词字典中,就存储文件的索引,否则就添加索引到索引列表后
for word in word_list:
if word not in word_dict:
word_dict[word]=[index]
else:
word_dict[word].append(index)
return word_dict
基本的内容我们有了,再考虑我们的输入,我们希望实现在控制台输入几个单词,找到最符合的几个文件。我们将输入存储为单词列表,以此判断该单词是否出现在文件中,如果出现了,我们将该单词对应的文件的索引+1,否则继续判断下一个单词。之后我们得到了关于文件索引次数的字典,我们按次数从大到小排列,然后取前几个作为我们最后的结果。当然,我们需要的是原始的文件名,因此,我们还要将索引映射回文件名,相关代码如下:
def get_topk(count,topk=None):
print(count)
file_index = []
#如果topk超出了返回的数目,则有多少显示多少
if topk > len(count):
for i in range(0,len(count)):
file_index.append(int(count[i][0]))
return file_index
if len(count)<0:
print("没有找到相关的文件")
return False
else:
for i in range(0,topk):
file_index.append(int(count[i][0]))
return file_index
#得到文件名
def get_files(file_index,files_dict):
res=[]
for i in file_index:
res.append(files_dict[i])
return res
主函数:
def main():
print("请输入要查找的内容,不同单词间','隔开:")
words = input().split(',')
#获得文件名和文件名索引字典
files_name, files_dict = file_store()
#提取关键词或分词
transform(files_name)
#倒排索引建立
word_dict = invert_index()
count={}
#统计文件索引的次数
for word in words:
if word in word_dict:
for file in word_dict[word]:
if file not in count:
count[file]=1
else:
count[file]+=1
else:
continue
#按次数从大到小排列
count=sorted(count.items(),key=lambda i:i[1],reverse=True)
#返回前k个文件索引
file_index=get_topk(count,topk=3)
if file_index != False:
print("与之描述最可能的文件是:")
#返回文件名,并输出结果
res=get_files(file_index,files_dict)
print(res)
最后,我们运行主函数:
if __name__ == '__main__':
main()
最终结果:
我们将topk改为3:
【原创】python倒排索引之查找包含某主题或单词的文件的更多相关文章
- 使用DOS命令查找包含某一字符串的所有文件
在windows系统下,来查找并修改指定目录下包含某一字符串的所有文件,麻烦又费时.其实在DOS命令中,提供了Findstr命令来查找指定的一个或多个文件文件中包含(或通过参数 /V来控制不包含) ...
- 如何在python列表中查找某个元素的索引
如何在python列表中查找某个元素的索引 2019-03-15 百度上回复别人的问题,几种方式的回答: 1) print('*'*15,'想找出里面有重复数据的索引值','*'*15) listA ...
- linux下查找包含BOM头的文件和清除BOM头命令
查找包含BOM头的文件,命令如下: grep -r -I -l $'^\xEF\xBB\xBF' ./ 这条命令会查找当前目录及子目录下所有包含BOM头的文件,并把文件名在屏幕上输出. 但 ...
- sql server 查找包含字符串的对象
sql server 查找包含字符串的对象 SELECT sm.object_id, OBJECT_NAME(sm.object_id) AS object_name, o.type, o.type_ ...
- Linux下查找包含BOM头的文件和清除BOM头命令 2014-08-16 12:30:50
Linux下查找包含BOM头的文件和清除BOM头命令 2014-08-16 12:30:50 分类: 系统运维 查找包含BOM头的文件,命令如下: 点击(此处)折叠或打开 grep -r -I -l ...
- 用Python和FFmpeg查找大码率的视频文件
用Python和FFmpeg查找大码率的视频文件 本文使用Python2.7, 这个工作分两步 遍历目录下的视频文件 用ffprobe获取是视频文件的码率信息 用ffprobe 获取json格式的视频 ...
- Python实现二分查找
老生常谈的算法了. #!/usr/bin/python # -*- coding:utf-8 -*- # Filename: demo.py # 用python实现二分查找 def binarySea ...
- hdu 2896 病毒侵袭 AC自动机(查找包含哪些子串)
病毒侵袭 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- java 遍历指定目录下的文件夹并查找包含指定关键字的文件
输入指定关键字,在制定目录中查找包含关键字的文件,返回包含指定关键字的文件路径. package net.xsoftlab.baike; import java.io.File; import jav ...
随机推荐
- WampServer配置可局域网访问站点
一 WampServer3.1.7版本 二 需求:项目开发阶段,服务器还未购买,前端需要调用接口进行测试,于是想到了在本地搭设一个站点,可以局域网内访问 三 先为这个项目单独在本地设置一个端口,比如我 ...
- python程序调用C/C++代码
这篇用来记录在些模拟Canoe生成CAN数据桢工具时遇到的问题, 生成CAN数据桢,主要分为两个关注点: 1.如何从can信号名获取到can信号的ID长度以及信号的起始位,并将信号值按照一定的规则填写 ...
- MySQL学习(三)MySQL锁与事务
本章我们着重讨论MySQL锁机制的特点,常见的锁问题,以及解决MySQL锁问题的一些方法或建议. 一.MySQL锁概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支 ...
- 从.NET CORE2.2升级到3.0过程及遇到的一些问题
RoadFlow工作流引擎从.NET Core2.2升级到3.0遇到了一些问题及解决方式这里记录一下. 1.DLL项目框架从2.2选择到3.0,这个没什么好说的,没有问题.重点的WEB层的一些变化. ...
- Jenkins项目构建
一:新建项目 (1)点击新建,输入项目名称--构建一个自由风格的软件项目,点击ok (2)创建项目名称,选择节点标签 (3)构建触发器-----设置每两分钟执行一次 其中有5个参数 (*****) 第 ...
- Python_MySQL数据库的写入与读取
[需求]1. 在数据库中创建表,且能按时间自动创建新表 2. 数据写入数据库 3. 从数据库读取数据 1. 创建表,并自动更新 def Creat_Table(InitMySQL,tabel_name ...
- 实验吧之【因缺思汀的绕过】(group by with rollup的注入利用)
打开页面,查看源代码,发现存在source.txt(http://ctf5.shiyanbar.com/web/pcat/source.txt),如下: <?php error_reportin ...
- 常用windows命令
目录 本教程概述 用到的工具 标签 简介 1.cmd的一些规则 2.cd切换目录命令 3.dir显示目录命令 4.type显示文本内容 5.del 删除文件 6.查看IP地址 7.net 命令 8.n ...
- 从前端到全栈:JavaScript逆袭之路
JavaScript如何做到上天入地无所不能?JavaScript真的能一统江湖吗? 背景 近年来,前端技术日新月异,前端已经不仅仅是网页,更多的开始由狭义向广义发展. 先后涌现出了具备后端能力的no ...
- go-json类
package main import ( "encoding/json" "fmt" ) /* { "company":"itc ...