精华内容
下载资源
问答
  • 文件存储中的客户端上跨多个文档进行搜索PDFTron文档搜索PDFTron文档搜索演示了如何构建一个应用程序,用户可以使用以下程序多个文档中进行搜索:PDFTron PDF SDK用于文本提取和文档查看Firebase用于存储Algolia...
  • solr 搜索引擎如何添加pdf文档 进行索引 我试过了,可以添加pdf文件,可是只有文件的名称能搜索到,如何我要是通过文件的内容进行搜索呢,该怎么做,请各位指教
  • 用C#实现PowerPoint文档搜索文本

    千次阅读 2007-03-22 00:19:00
    用编程的方式根据对象模型很容易实现Word、Excel文档搜索文本,PowerPoint里面也同样如此,使用对象模型有助于我们了解office的文档结构。 搜索的思路和方法基本是一样的,用PowerPoint应用程序对象打开指定...
    用编程的方式根据对象模型很容易实现在Word、Excel文档中搜索文本,在PowerPoint里面也同样如此,使用对象模型有助于我们了解office的文档结构。 

      搜索的思路和方法基本是一样的,用PowerPoint应用程序对象打开指定的文档,用文档对象获取文档,再使用合适的对象将文档分割成搜索范围适中的对象进行搜索。

      打开PowerPoint的VBA帮助文档VBAPP10.CHM,根据对象模型图,很容易找到我们需要的几个集合和对象:Application、Presentations、Presentation、Slides、Slide、TextFrame、TextRange。其中Presentation代表一个 PowerPoint 文档,Slide表示PowerPoint文档中的单张幻灯片,TextFrame是幻灯片上的文本框,TextRange是文本框中的文本。

      打开PowerPoint文档:

    string  filename = " " ;

    PowerPoint.Application pa
    = new  PowerPoint.ApplicationClass();
    PowerPoint.Presentation pp
    = pa.Presentations.Open(filename,
                    Microsoft.Office.Core.MsoTriState.msoTrue,
                    Microsoft.Office.Core.MsoTriState.msoFalse,
                    Microsoft.Office.Core.MsoTriState.msoFalse);

      Open()方法的第三个参数在帮助文档中的说明如下:

      Untitled     可选。MsoTriState 类型。指定文件是否有标题。

      因为是Untitled,所以按照上面的代码,打开文档之后才能引用PowerPoint文档的标题,如果不想使用标题,就要把枚举msoFalse改成msoTrue。
    搜索文本:

    string [] strKeyWordList = {} ;     // 要搜索的文本
    PowerPoint.TextRange oText;
    foreach (PowerPoint.Slide slide  in  pp.Slides)
    {
        
    foreach(PowerPoint.Shape shape in slide.Shapes)
        
    {
            
    foreach(string strKeyWord in strKeyWordList)
            
    {
                oText
    =null;
                oText
    =shape.TextFrame.TextRange.Find(strKeyWord,0,Microsoft.Office.Core.MsoTriState.msoFalse,Microsoft.Office.Core.MsoTriState.msoTrue);
                
    if (oText!=null)
                
    {
                    MessageBox.Show(
    "文档中包含指定的关键字 "+strKeyWord+" !","搜索结果",MessageBoxButtons.OK);
                    
    continue;
                }

            }

        }

    }
    用编程的方式根据对象模型很容易实现在Word、Excel文档中搜索文本,在PowerPoint里面也同样如此,使用对象模型有助于我们了解office的文档结构。 

      搜索的思路和方法基本是一样的,用PowerPoint应用程序对象打开指定的文档,用文档对象获取文档,再使用合适的对象将文档分割成搜索范围适中的对象进行搜索。

      打开PowerPoint的VBA帮助文档VBAPP10.CHM,根据对象模型图,很容易找到我们需要的几个集合和对象:Application、Presentations、Presentation、Slides、Slide、TextFrame、TextRange。其中Presentation代表一个 PowerPoint 文档,Slide表示PowerPoint文档中的单张幻灯片,TextFrame是幻灯片上的文本框,TextRange是文本框中的文本。

      打开PowerPoint文档:

    string  filename = " " ;

    PowerPoint.Application pa
    = new  PowerPoint.ApplicationClass();
    PowerPoint.Presentation pp
    = pa.Presentations.Open(filename,
                    Microsoft.Office.Core.MsoTriState.msoTrue,
                    Microsoft.Office.Core.MsoTriState.msoFalse,
                    Microsoft.Office.Core.MsoTriState.msoFalse);

      Open()方法的第三个参数在帮助文档中的说明如下:

      Untitled     可选。MsoTriState 类型。指定文件是否有标题。

      因为是Untitled,所以按照上面的代码,打开文档之后才能引用PowerPoint文档的标题,如果不想使用标题,就要把枚举msoFalse改成msoTrue。
    搜索文本:

    string [] strKeyWordList = {} ;     // 要搜索的文本
    PowerPoint.TextRange oText;
    foreach (PowerPoint.Slide slide  in  pp.Slides)
    {
        
    foreach(PowerPoint.Shape shape in slide.Shapes)
        
    {
            
    foreach(string strKeyWord in strKeyWordList)
            
    {
                oText
    =null;
                oText
    =shape.TextFrame.TextRange.Find(strKeyWord,0,Microsoft.Office.Core.MsoTriState.msoFalse,Microsoft.Office.Core.MsoTriState.msoTrue);
                
    if (oText!=null)
                
    {
                    MessageBox.Show(
    "文档中包含指定的关键字 "+strKeyWord+" !","搜索结果",MessageBoxButtons.OK);
                    
    continue;
                }

            }

        }

    }

     
    展开全文
  • 自动搜索到网络中各种文库网站的文档,并生成列表显示下载费用、文档大小、网友评分、下载量、网友评价等文档说明,有效减少文档搜索中各种繁琐的步骤,使用户能更为快速地搜索到所需要的文档进行批量下载。...
  • 易语言包含子目录的文档搜索源码,包含子目录的文档搜索,单文件搜寻,多文件搜寻
  • 如何 Windows 上 使用 ONLYOFFICE 协作编辑文档

    万次阅读 多人点赞 2018-02-19 20:21:39
    1、说明——可以加我qq504284沟通。...但是这里告诉我们,需要进行文档管理和存储的二次开发。它api里现成的开发好的文档管理平台,有java,node.js,PHP等,可能不具备权限功能吧。 Please note, thatONLYOFFICE...

    1、说明——可以加我qq504284沟通。

    ONLYOFFICE Document Server提供文档协作的服务功能,支持Word,Excel和PowerPoint以及国产WPS的协作。但是这里告诉我们,需要进行文档管理和存储的二次开发。它api里现成的开发好的文档管理平台,有java,node.js,PHP等,可能不具备权限功能吧。

    Please note, that ONLYOFFICE Document Server includes the documenteditordocument editing servicedocument command service and documentconversion service.The document manager and documentstorage service areeither included to Community Server or must be implemented by the softwareintegrators who use ONLYOFFICE Document Server on their own server.

    它自己的ONLYOFFICE/CommunityServer就是管理文件用的,是一个庞大的项目管理系统。

    ONLYOFFICE CommunityServer is a free open source collaborative system developed to managedocuments, projects, customer relationship and email correspondence, all in oneplace.

    Nextcloud,可道云等云盘系统也支持ONLYOFFICE协作服务,我用Golang语言开发的EngineerCMS来实现ONLYOFFICE的文档管理和存储,调用ONLYOFFICE Document Server服务来进行文档协作,权限完全按照官方的community。

    协作的好处在于少了来回传递文档,少了汇总的负责人,特别是十多人合作编写文档的时候,汇总的工作量大,容易出错,任何人稍微修改一点,都要重新传递整个文档,汇总后还要再次发给大家核对……。

    协作也可以应用于校审流程,校核和审查直接在文档上修改即可。

    其他如月报的合作,工作任务表的更新:每个人的任务表要随时更新,除非用专业的任务管理软件,否则用Excel表格的话,也是要负责人汇总更新表格,应付领导检查。

    会议纪要写好了,把链接发给大家,有意见直接在上面修改补充。

    投标要多人协作的话,用这个平台也是不错的。

    报表的汇总。

    市场上协作的平台不下几十种,著名的如石墨,一起写,腾讯文档协作TIM,Google Doc,office365,office online等,基本按人月收费,免费的有人数限制,并且想自己部署在局域网的话也不大可能。你的文档上传给他们或许有诸多不便呢。比如银行的报表,嘿嘿,你懂的。

    所以,我就在ONLYOFFICE Document Server基础上用Golang语言开发了文档管理和存储功能,方便大家免费无限制任意部署的需求。

    总的思路就是比如在局域网的某台windows(推荐用linux-centos,因为很稳定)电脑上安装docker容器来运行ONLYOFFICE Document Server,然后运行EngineerCMS来调用ONLYOFFICE Document Server的服务。在云服务器上部署也是一个道理。

    ONLYOFFICE随着版本的不断更迭,功能越来越接近MSOFFICE,比如有文档结构(word文档导航),历时版本的对照功能,excel里的文字删除线、筛选、透视表等。

    2、安装准备

    如果是局域网,部署的电脑拥有固定ip(下文叫宿主机,切记)。电脑能打开cup的虚拟功能。如果部署到云主机,道理是一样的。

    环境是win7以上,win10以下。Win10区别就是安装的docker软件不同而已(win10不要安装docker toolbox了),win10不需要设置端口转发。

    linux就更简单了。

    第一步:确定电脑打开了cpu虚拟打开。https://jingyan.baidu.com/article/22fe7ced3b4c003002617f17.html

    第二步:下载和安装docker toolbox(win7),默认安装即可。下载地址http://get.daocloud.io/,下载支持旧版windows的docker toolbox,win10就直接下载docker了。切记,win下安装完成docker后,启动docker的时候断网,启动后可以联网。

    第三步:启动docker后在里面拉取Onlyoffice Document Server 的Docker镜像,然后运行即可。

    下面过程看起来繁琐,等你理解后其实就2步:拉取镜像(或导入离线包),然后运行再就是在文档管理平台上配置一下IP和端口。

    3、拉取ONLYOFFICE Document Server 的Docker镜像(可选)

    拉取镜像:启动docker,在里面输入命令docker pull onlyoffice/documentserver

    (注意:docker要断网启动!!切记,启动后再联网。如果已经运行了onlyoffice document server, 下次开机,重新启动docker后,不需要再运行onlyoffice的,当你启动docker后,OO已经启动了)

    可以用我做好的镜像导入(离线包导入),已经导入好了中文字体,修正了几个翻译错误,可以省略第5步,从第4步直接跳过第5步到第6步。

    建议用离线的,导入离线包命令为:docker load < fei6onlyoffice5.4.2.tar

    fei6onlyoffice5.4.2.tar,这个包解决了中文字体名称问题。

    下载放到docker命令行对应的目录下,方便运行命令导入(load)这个镜像。一般在c盘-users-administrator或者其他用户名下(在docker命令行里输入dir,看看当前目录下有哪些文件,一般就能找到这个目录了。)

    4、启动——映射至9000端口(运行镜像后变成容器)

    docker run -i -t -d -p 9000:80 onlyoffice/documentserver

    如果是导入的镜像,上面的命令中onlyoffice/documentserver用镜像id代替,查阅镜像用docker images命令。

    运行后就可以通过http://192.168.99.100:9000访问OO服务的欢迎界面了,运行后的我们称之为容器。

    5、添加容器onlyofficedocument server的字体(可省略)

    在网盘中下载字体winfont压缩包。字体来源于https://github.com/neroxps/Docker-Only-Office-Chinese-font和win10系统,win10系统提取中文字体的方法:控制面板——搜字体——查看安装的字体——再在搜索栏输入中文 2个字,这些就是需要的中文字体了。OO首次加载会比较慢,因为加载中文字体,一般达到50M以上。需要精简字体的方法,可以查阅网络或找我。

    Administrator@604TFALNDKDKJWCMINGW64 ~/winfont

    //将当前文件夹C:\Users\Administrator\下的winfont文件夹内的字体全部拷贝到容器的文件夹/usr/share/fonts/truetype中

    字体文件在我的网盘中:https://pan.baidu.com/s/1JgYvx_Rpl6oF4_QMNaU3qg

    提取码:jlt6

    $ tar -cv * | docker exec -i 6df tar x -C/usr/share/fonts/truetype

    kaiu.ttf

    msjh.ttc

    msjhbd.ttc

    msjhl.ttc

    msyh.ttc

    msyh.ttf

    msyhbd.ttc

    msyhl.ttc

    simfang.ttf

    simhei.ttf

    simkai.ttf

    simli.ttf

    simsun.ttc

    simsunb.ttf

    simyou.ttf

    ……

    Administrator@604TFALNDKDKJWCMINGW64 ~/winfont

    //进入容器内

    $ docker exec -it 6df /bin/bash

    root@6dfa5705aaef:/#sudo mkfontscale

    root@6dfa5705aaef:/#sudo mkfontdir

    root@6dfa5705aaef:/#sudo fc-cache -fv

    /usr/share/fonts:caching, new cache contents: 0 fonts, 1 dirs

    …………

    fc-cache:succeeded

    root@6dfa5705aaef:/#exit

    exit

    //退出容器

    Administrator@604TFALNDKDKJWCMINGW64 ~/winfont

    $ docker exec 6df /usr/bin/documentserver-generate-allfonts.sh

    GeneratingAllFonts.js, please wait...Done

    onlyoffice-documentserver:docservice:stopped

    onlyoffice-documentserver:docservice:started

    onlyoffice-documentserver:converter:stopped

    onlyoffice-documentserver:converter:started

     如果机器重启后,断网情况下启动docker,此时不需要再运行docker run命令,OO服务已经随DOCKER启动了。

    完成后记得清理chrome浏览器缓存,否则新导入的字体不会生效。chrome浏览器:设置—高级—隐私设置和安全性—清除浏览数据—时间范围选择时间不限……

    具体替换字体的命令见下图,很详细具体了。

    插图上写的界面汉化不对,这些只是导入中文字体而已,和界面汉化无关。界面中文化其实就是在页面中将 "lang": "zh-CN"

    修正excel、word、ppt翻译错误:

    Administrator@604TFALNDKDKJWC MINGW64 ~/zh

    $ docker exec -it 6df /bin/bash

    root@6dfa5705aaef:/#cd /var/www/onlyoffice/documentserver/web-apps/apps/spreadsheeteditor/main/locale/

    root@6dfa5705aaef:/var/www/onlyoffice/documentserver/web-apps/apps/spreadsheeteditor/main/locale#ls

    cs.json en.json  fr.json  ja.json nl.json  pt.json  sk.json tr.json  vi.json

    de.json es.json  it.json  lv.json pl.json  ru.json  sl.json uk.json  zh.json

    root@6dfa5705aaef:/var/www/onlyoffice/documentserver/web-apps/apps/spreadsheeteditor/main/locale#exit

    exit

    Administrator@604TFALNDKDKJWC MINGW64 ~/zh

    $ tar-cv zh.json | docker exec -i 6df tar x -C /var/www/onlyoffice/documentserver/web-apps/apps/spreadsheeteditor/main/locale/

    zh.json

    word的翻译文件/var/www/onlyoffice/documentserver/web-apps/apps/documenteditor/main/locale/

    $ tar-cv zh.json | docker exec -i 6df tar x -C /var/www/onlyoffice/documentserver/web-apps/apps/documenteditor/main/locale/

    6、还可以替换帮助文件为中文……

    /var/www/onlyoffice/documentserver/apps/presentationeditor/main/resources/help/zh/Contents.json

    /var/www/onlyoffice/documentserver/apps/spreadsheeteditor/main/resources/help/zh/Contents.json

    /var/www/onlyoffice/documentserver/apps/documenteditor/main/resources/help/zh/Contents.json

    做完以上工作,你可以将修改后的容器保存为新的镜像,然后save导出后给其他机器用。

    docker commit将修改后镜像保存到本地,参数是容器ID,新名字:版本标志

    #docker ps -all

    CONTAINER ID IMAGE   COMMAND    CREATED       STATUS          PORTS   NAMES

    b3426410ff43 centos:7 "/bin/bash" 4 minutes ago   Exited (0) 4 seconds ago     centos7ssh

    #docker commit b59myimage/centos7-ssh(这个是例子)

    下次可以输入刚保存的名字启动修改了字体的镜像了。

    导出镜像——一定要导出保存,否则docker经常自己升级,容器啊,镜像啊,都会丢失,追悔莫及。

    所以,启动docker的时候要关闭网络,否则它自动升级。等docker完全启动后,再打开网络。

    docker save -o onlyoffice.tar onlyoffice/documentserver

    6、运行和修改文档管理平台EngineerCMS

    直接去https://github.com/3xxx/engineercms查看源码,自己编译。

    直接去链接:https://pan.baidu.com/s/1MDJ-QfCmv_LiychDSLn8jw 提取码:nhar 下载软件包,直接运行engineercms即可用浏览器chrome访问127.0.0.1了,不用配置环境,因为它是golang语言编写的跨平台的可执行文件。如果运行出现闪退,则在conf文件夹下更改app.conf文件中的端口号,或者修改runmode为prod模式。

    (1)运行前要替换engineercms\views\onlyoffice\onlyoffice.tpl中的3处 IP 和 端口号,如果engineercms和docker安装在同一个电脑上,那么三个IP相同,但端口号是不同的,见下面的6.1节。

    2)docker toolbox访问前要按照下文中第7节中的方法设置宿主机(安装docker的电脑)virtualbox的端口转发。win10的windows docker不用设置端口转发了。

    有问题联系我QQ504284,微信hotqin999

    http://blog.csdn.net/hotqin888

    6.1协作编辑页面要根据你的情况进行修改(ip地址、中文界面

    一定要用ip,不要用localhost、127.0.0.1之类的代替本机ip,本机调试要用192.168.99.100

    注意:下文只是标识出需要修改的3处ip和端口号位置,代码并不能直接拷贝过去运行。请在engineercms文件夹中对应的原始文件上进行修改。

    engineercms\views\onlyoffice\onlyoffice.tpl:

    
    <!DOCTYPE html>
    <html style="height: 100%;">
    <head>
       <title>fei-OnlyOffice</title>
    </head>
    <body style="height: 100%; margin: 0;">
        <divid="placeholder" style="height: 100%"></div>
        <script type="text/javascript"src="http://安装docker电脑的ip:9000/web-apps/apps/api/documents/api.js"></script>
        <scripttype="text/javascript">
            //alert({{.Doc.FileName}});
           window.docEditor = new DocsAPI.DocEditor("placeholder",
                {
                   "document": {
                       "fileType": "{{.fileType}}",
                       "key": "{{.Key}}",//"Khirz6zTPdfd7"
                       "title": "{{.Doc.FileName}}",
                       "url": "http://运行engineercms电脑的ip:端口号/attachment/onlyoffice/{{.Doc.FileName}}"
                    },
                   "documentType": "{{.documentType}}",
                   "editorConfig": {
                       "callbackUrl": "http://运行engineercms电脑的ip:端口号/url-to-callback?id={{.Doc.Id}}",
                       "user": {
                           "id": "{{.Uid}}",
                           "name": "{{.Uname}}"
                       },
                       "lang": "zh-CN",//"en-US",菜单中文化
                    },
                   "height": "100%",
                   "width": "100%"
                });
       </script>
    </body>
    </html>

    7、端口转发

    http://blog.csdn.net/maodou95838/article/details/78194830?locationNum=1&fps=1#0-qzone-1-51693-d020d2d2a4e8d1a374a433f596ad1440

    前文第4节运行ONLYOFFICE DOCUMENT SERVER:

    docker run -i -t -d -p 9000:80 onlyoffice/documentserver

    -d:后台运行 

    -p 9000:80 :端口映射,前一个9000代表虚拟机的端口,后一个80代表docker容器的端口 

    命令执行完成后,可以通过http://192.168.99.100:9000访问OO服务的欢迎界面。

    这时只能在你自己的机器上访问,同一个局域网中的其他机器是不能访问的,原因是:Windows上的docker是运行在一个虚拟机里面的,看官方给的图: 

     要让别的机器也访问到,需要配置一下虚拟机。设置如下: 

    双击运行安装docker toolbox生成的Oracle VMVirtualBox。

    点击端口转发:下图中主机IP为安装docker的电脑IP,主机端口为9000,子系统IP为192.168.99.100,子系统端口为9000

    这样配置完成后,别的机器也可以访问docker 容器了。

    下文的开发仅供兴趣参考。

    8、二次开发engineercms

    8.1 协作编辑页面

    <!DOCTYPE html>
    <html style="height: 100%;">
    <head>
       <title>fei-OnlyOffice</title>
    </head>
    <body style="height: 100%; margin: 0;">
        <divid="placeholder" style="height: 100%"></div>
        <script type="text/javascript"src="http://安装docker电脑的ip:9000/web-apps/apps/api/documents/api.js"></script>
        <scripttype="text/javascript">
            //alert({{.Doc.FileName}});
            window.docEditor = newDocsAPI.DocEditor("placeholder",
                {
                   "document": {
                       "fileType": "{{.fileType}}",
                       "key": "{{.Key}}",//"Khirz6zTPdfd7"
                       "title": "{{.Doc.FileName}}",
                       "url": "http://运行engineercms电脑的ip:端口号/attachment/onlyoffice/{{.Doc.FileName}}"
                    },
                    "documentType":"{{.documentType}}",
                   "editorConfig": {
                       "callbackUrl": "http:// 运行engineercms电脑的ip:端口号/url-to-callback?id={{.Doc.Id}}",
    
                       "user": {
                           "id": "{{.Uid}}",
                           "name": "{{.Uname}}"
                       },
                       "lang": "zh-CN",//"en-US",
                    },
                   "height": "100%",
                   "width": "100%"
                });
       </script>
    </body>
    </html>

    8.2 协作页面的保存和回调——下面是go语言,官方文档有php java node.js等。

    type Callback struct {
       Key         string   `json:"key"`
       Status      int     `json:"status"`
       Url         string   `json:"url"`
       Changesurl  string  `json:"changesurl"`
       History     history `json:"history"`
       Users       []string `json:"users"`
       Actions     []action `json:"actions"`
       Lastsave    string  `json:"lastsave"`
       Notmodifiedbool     `json:"notmodified"`
    }
    type action struct {
       Type   int
       userid string
    }
    type history struct {
     changes       []change
       serverVersionstring
    }
    type change struct {
       created string
       User    User1
    }
    
    type User1 struct {
       id   string
       name string
    }
    
    //关闭浏览器标签后获取最新文档保存到文件夹
    func (c *OnlyController) UrltoCallback() {
       // pk1 :=c.Ctx.Input.RequestBody
       id :=c.Input().Get("id")
       //pid转成64为
       idNum, err :=strconv.ParseInt(id, 10, 64)
       if err != nil {
          beego.Error(err)
       }
       //根据附件id取得附件的prodid,路径
       onlyattachment,err := models.GetOnlyAttachbyId(idNum)
       if err != nil {
          beego.Error(err)
       }
    
       var callbackCallback
       json.Unmarshal(c.Ctx.Input.RequestBody,&callback)
       ifcallback.Status == 1 || callback.Status == 4 {
          c.Data["json"]= map[string]interface{}{"error": 0}
          c.ServeJSON()
       } else ifcallback.Status == 2 {
          resp, err :=http.Get(callback.Url)
          if err != nil{
             beego.Error(err)
          }
          body, err :=ioutil.ReadAll(resp.Body)
         if err != nil{
             beego.Error(err)
         }
          deferresp.Body.Close()
          if err != nil{
             beego.Error(err)
          }
          f, err :=os.create(".\\attachment\\onlyoffice\\"+onlyattachment.FileName)
          if err != nil{
             beego.Error(err)
          }
          deferf.Close()
          _, err =f.Write(body)
          if err != nil{
             beego.Error(err)
          } else {
             err =models.UpdateOnlyAttachment(idNum)
             if err !=nil {
                beego.Error(err)
             }
          }
          c.Data["json"]= map[string]interface{}{"error": 0}
          c.ServeJSON()
       }
    }

    engineercms的文档管理: 根据官方community的样子,做了权限管理和历时版本对照功能。

     word文件协作效果:

    展开全文
  • API 文档搜索引擎

    千次阅读 热门讨论 2021-03-13 20:37:20
    该项目主要实现了前端页面的搜索输入需要搜索的 Java API 文档的关键字,对后端发出请求,后端将处理后的结果返回给前端展示,并且按照一定的权重排序展示出来。 开发环境:IDEA、Tomcat 9、Maven、JDK1.8 ...

    项目简介

    该项目主要实现了在前端页面的搜索框内输入需要搜索的 Java API 文档的关键字,对后端发出请求,后端将处理后的结果返回给前端展示,并且按照一定的权重排序展示出来。

    • 开发环境:IDEA、Tomcat 9、Maven、JDK1.8
    • 相关技术:正排索引、倒排索引、分词技术、过滤器、Servlet、Json、Ajax
    • 本地资源:Java API 文档(点击这里获取)

    项目详解

    我主要从一下几个方面进行详解:

    • 几个用于保存数据的实体类
    • 通过本地 API 构建正排索引
    • 构建倒排索引,并创建实体类
    • 后端处理逻辑
    • 测试

    实体类

    • DocInfo

    每一个 api 文档的 html 文件都对应一个该类,在该类中主要有四个属性字段,分别是:

    id:类似于数据库的主键可以对应单独一个文档
    title:文档的文件名
    content:文档的正文部分
    url:Oracle 官网上的 api 文档下 htmlurl 地址

    /**
     * 每一个html文件对应一个文档对象
     */
    public class DocInfo {
        private Integer id; 
        private String title; 
        private String content; 
        private String  url; 
    }
    
    • Weight

    该类表示的是某个关键词在某个文档中的权值,配合 Map<String, List<Weight>> 使用,表示某个关键词对应的所有文档及其对应的权值。在该类中主要有三个属性字段,分别是:

    keyword:关键词
    docInfo:该关键词对应的文档类
    weight:该关键词在该文档中的权值

    public class Weight {
        private DocInfo docInfo; 
        private String keyword; 
        private int weight; 
    }
    
    • Result

    该类表示的是将搜索内容进行分词后,会得到多个关键词,每个关键词会对应多个文档,而其中不乏出现重复的文档,这时就需要对重复文档进行合并,用文档 ID 作为唯一标识,将 ID 相同的文档的权值根据关键字先后顺序不同进行加权操作,最终所有会匹配到的文档都是唯一的,根据权值对其进行排序后返回前端展示。在该类中主要有五个属性字段,分别是:

    id:文档的唯一标识
    weight:合并后该文档的加权权值
    title:该文档的标题
    url:该文档的 url
    decs:该文档的描述

    public class Result {
        private Integer id;
        private int weight;
        private String title;
        private String url;
        private String desc;
    }
    

    构建正排索引

    遍历 api 文档存储的目录,对每个 html 文件进行读取解析,并且将需要的信息提取出来并且封装到实体类 DocInfo中,然后将所有提取到的信息持久化到本地的 raw_data 文件中。

    public class Parser {
    
        // api目录
        public static final String API_PATH = "E:\\IDEA2020\\searchEngine\\jdk-8u261-docs-all\\docs\\api";
        // 构建的本地文件的正拍索引
        public static final String RAW_DATA = "E:\\IDEA2020\\searchEngine\\jdk-8u261-docs-all\\docs\\raw_data.txt";
        // 官方api文档的根路径
        public static final String API_BASE_PATH = "https://docs.oracle.com/javase/8/docs/api";
    
        public static void main(String[] args) throws IOException {
            // api本地路径下所有的html文件找到
            List<File> htmls = listHtml(new File(API_PATH));
            List<DocInfo> list = new ArrayList<>();
            // 输出流
            FileWriter fw = new FileWriter(RAW_DATA);
            BufferedWriter bw = new BufferedWriter(fw);
    
            for (File html : htmls) {
                DocInfo doc = parseHtml(html);
    
                // 输出格式为:title + '\3' + url + '\3' + content
                bw.append(doc.getTitle()).append(String.valueOf('\3'));
                bw.append(doc.getUrl()).append(String.valueOf('\3'));
                bw.append(doc.getContent()).append("\n");
    
                bw.flush();
            }
            bw.close();
            fw.close();
    
        }
    
        // 将html文件转化为DocInfo对象
        private static DocInfo parseHtml(File html) {
            DocInfo docInfo = new DocInfo();
            docInfo.setTitle(html.getName().substring(0, html.getName().length() - 5));
            docInfo.setUrl(API_BASE_PATH + html.getAbsolutePath().substring(API_PATH.length()));
            docInfo.setContent(parseContent(html));
            return docInfo;
        }
        // 将html文件的内容部分提取
        public static String parseContent(File html) {
            StringBuilder sb = new StringBuilder();
            try {
                FileReader fr = new FileReader(html);
                boolean isContext = false;
                int i;
                while ((i = fr.read()) != -1) {
                    char c = (char) i;
                    if (isContext) {
                        if (c == '<') {
                            isContext = false;
                        } else if (c == '\n' || c == '\r') {
                            sb.append(" ");
                        } else {
                            sb.append(c);
                        }
                    } else if (c == '>'){
                        isContext = true;
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
    
            return sb.toString().trim();
        }
    
        // 递归遍历子文件
        private static List<File> listHtml(File dir) {
            File[] children = dir.listFiles();
            List<File> list = new ArrayList<>();
    
            for (File child : children) {
                if (child.isDirectory()) { // 子文件夹:递归调用文件夹内的html文件
                    list.addAll(listHtml(child));
                } else if (child.getName().endsWith(".html")){ // html文件
                    list.add(child);
                }
            }
    
            return list;
        }
    
    }
    

    构建倒排索引

    1. 首先加载本地文件内容,加载到正排索引的集合中
    2. 根据正排索引构建倒排索引(标题权重10,内容权重1),具体实现如下:

    首先有一个 Map<String, List<Weight>> 集合表示一个关键词对应多个 api 文档,然后遍历存储所有 DocInfo 类的 List<DocInfo>,对于每一个 DocInfo 都分为对标题和内容进行分词,分词技术使用的是一个开源的分词工具 Ansj,可以很高效的将句子进行分词处理。我们将分词之后的关键词加入 Map 集合,关键词作为键,Weight类的集合作为值,用来保存每个关键词在对应的每个 api 文档中的权值。对于权值的计算,我们自定义的认为如果出现在标题中那么权值 +10,如果出现在文章中,那么权值 +1,从而构建好倒排索引。

    public class Index {
    
        // 正排索引
        public static final List<DocInfo> FORWARD_INDEX = new ArrayList<>();
        // 倒排索引
        public static final Map<String, List<Weight>> INVERTED_INDEX = new HashMap<>();
    
        // 构建正排索引
        public static void buildForwardIndex(){
            try {
                FileReader fr = new FileReader(Parser.RAW_DATA);
                BufferedReader br = new BufferedReader(fr);
                String line = null;
                int id = 0;
                while ((line = br.readLine()) != null) {
                    if (line.trim().equals("")) continue;
                    String[] parts = line.split("\3");
                    DocInfo docInfo = new DocInfo();
                    docInfo.setId(++id);
                    docInfo.setTitle(parts[0]);
                    docInfo.setUrl(parts[1]);
                    docInfo.setContent(parts[2]);
                    FORWARD_INDEX.add(docInfo);
    //                if (id == 5) break;
                }
            } catch (IOException e) {
                throw new RuntimeException(e); // 直接抛出异常,再构建阶段就发现异常
            }
        }
    
        // 构建倒排索引: 从 java内从中的正排索引获取文档信息来构造
        public static void buildInvertedIndex(){
            Map<String, Weight> temp = new HashMap<>();
            for (DocInfo docInfo : FORWARD_INDEX) {
                // 一个doc,分别对标题和正文分词,每一个分词生成一个weigh对象,需要计算权重
    
                // 计算title权重
                String title = docInfo.getTitle();
                List<Term> terms = ToAnalysis.parse(title).getTerms(); // 获取title分词结果
                for (Term term : terms) {
                    if (temp.containsKey(term.getName())) {
                        temp.get(term.getName()).setWeight(temp.get(term.getName()).getWeight() + 10);
                    } else {
                        Weight we = new Weight();
                        we.setWeight(10);
                        we.setDocInfo(docInfo);
                        we.setKeyword(term.getName());
                        temp.put(term.getName(), we);
                    }
                }
    
                // 计算context权重
                String content = docInfo.getContent();
                terms = ToAnalysis.parse(content).getTerms(); // 获取title分词结果
                for (Term term : terms){
                    if (temp.containsKey(term.getName())) {
                        temp.get(term.getName()).setWeight(temp.get(term.getName()).getWeight() + 1);
                    } else {
                        Weight we = new Weight();
                        we.setWeight(1);
                        we.setDocInfo(docInfo);
                        we.setKeyword(term.getName());
                        temp.put(term.getName(), we);
                    }
                }
    
                // 将该docInfo的关键词注入到总的关键词map
                for (String key : temp.keySet()) {
                    if (INVERTED_INDEX.containsKey(key)) {
                        INVERTED_INDEX.get(key).add(temp.get(key));
                    } else {
                        List<Weight> list = new ArrayList<>();
                        list.add(temp.get(key));
                        INVERTED_INDEX.put(key, list);
                    }
                }
    
                // 注入完成后,释放temp内容
                temp.clear();
    
            }
        }
    }
    

    后端逻辑(Servlet)

    首先接收前端发来的请求信息(搜索内容),使用分词技术对搜索内容进行分词操作,会得到多个关键词,其根据先后排序有不同的权重,从第一个关键词开始查找,可以得到单个分词的 Weight 集合,里面包括包含该分词的所有文档及其权值。因为对于多个分词而言,可能出现一个文档包含多个分词的情况,所以这样就会出现文档重复的情况,故需要对搜索到的文档进行合并操作,具体操作由 Result 类以及 Map<Integer, Result> 配合完成,根据每个文档的唯一主键判断是否为同一文档,如果是同一个文档就对其值部分的 weight 属性字段进行权值相加操作,这样最后会得到不重复的结果集,最后对其进行按照权值降序排序,以 Json 格式返回给前端即可。(权值设定:设定初始权值为 100 ,对于多个关键字,按排序依次权值减半)

    代码如下:

    @WebServlet("/search")
    public class SearchServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("进入SearchServlet - doGet");
            // 构造返回给前端的内容,使用对象,在使用jackson序列化为json字符串
            Map<String, Object> map = new HashMap<>();
            // 解析请求的数据
            String query = req.getParameter("query");
            // 每个文档转换为一个Result(可能出现多个分词对应一个文档,需要进行文档合并)
            Map<Integer, Result> resultMap = new HashMap<>();
            // 初始权重为100,随着排序依次减半
            int w = 100;
            try {
                // 根据搜索内容处理搜索业务
                // 1. 根据搜索内容,进行分词,遍历每个分词
                List<Term> terms = ToAnalysis.parse(query).getTerms();
                for (Term term : terms) {
                    String word = term.getName(); // 单个分词
                    List<Weight> weightList = Index.INVERTED_INDEX.get(word); // 获取到单个分词的 Weight 集合
                    // 2. 每个分词,在倒牌中查找对应的文档(一个分词对一个多个文档)
                    for (Weight weight : weightList) {
                        final Integer id = weight.getDocInfo().getId();
                        // 文档合并
                        if (resultMap.containsKey(id)) {
                            // 存在id
                            resultMap.get(id).setWeight(resultMap.get(id).getWeight() + w);
                        } else {
                            // 不存在id
                            final Result temp = new Result(id, weight.getWeight(),
                                                            weight.getDocInfo().getTitle(),
                                                            weight.getDocInfo().getUrl(),
                                                            weight.getDocInfo().getContent().substring(0, 100) + "......");
                            resultMap.put(id, temp);
                        }
                    }
                    // 每过一个关键字,w减半
                    w >>= 1;
                }
                // 4. 文档合并后,根据权重对List<Result>进行排序
                List<Result> resultList = new ArrayList<>(resultMap.values());
                resultList.sort((o1, o2) -> o2.getWeight() - o1.getWeight());
    
                map.put("data", resultList);
                // 如果成功
                map.put("ok", true);
            } catch (Exception e) {
                e.printStackTrace();
                // 失败
                map.put("ok", false);
            }
    
            // 获取输出流
            PrintWriter pw = resp.getWriter();
            // 将map序列化为json对象,然后通过ajax传递给前端
            pw.print(new ObjectMapper().writeValueAsString(map));
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    

    还有一点就是使用过滤器在初始化的时候完成正排索引和倒排索引的构建,同时设置字符集编码为“UTF-8”,响应格式为 Json 格式。


    测试

    • 启动Tomcat,我们可以看到以下展示的是搜索页面
      在这里插入图片描述

    • 输入关键词 Map,点击 Search进行搜索,下面展示的搜索内容
      在这里插入图片描述

    • 随便点击一个链接,比如 TreeMap,我们可以看到会跳转至 Oracle 官网的 API 文档链接
      在这里插入图片描述


    结果表明搜索功能已经基本实现,后续还可以对其进行改进,比如缓存操作可以加快搜索速度,还有前端的美化,以及目前 api 文档的解析手法比较粗糙,可能会出现将代码解析至内容中的情况,所以后续还可以对解析手法进行进一步优化。代码已经上传至 GitHub,点此获取…

    展开全文
  • C#编程实现Excel文档搜索文本

    千次阅读 2007-03-22 00:22:00
    有了word文档中编程实现搜索文本的经验,excel中实现这个功能也并非难事。 打开Excel的VBA帮助,查看Excel的对象模型,很容易找到完成这个功能需要的几个集合和对象:Application、Workbooks、Workbook、...

    有了在word文档中编程实现搜索文本的经验,在excel中实现这个功能也并非难事。
     
      打开Excel的VBA帮助,查看Excel的对象模型,很容易找到完成这个功能需要的几个集合和对象:Application、Workbooks、Workbook、Worksheets还有Worksheet和Range。Application创建Excel应用,Workbooks打开Excel文档,Workbook获得Excel文档工作薄,Worksheets操作工作表集合,Worksheet获得单个工作表。
     
      搜索的思路对应上述集合和对象,可以这样表述:要搜索的文本可能存在Excel文档当中的某个工作表上,搜索应该遍历目标Excel文件的每个工作表中的有效区域,如果找到,则退出本次搜索,如果没有找到,则继续搜索直到完成本次搜索。
     
      跟Word对象模型不一样的是,Excel对象模型没有提供Find对象,不过没有关系,可以通过两种方法来实现,一个是通过Range对象的Find()方法来实现,另外一个比较麻烦,取得工作表Worksheet的有效区域UsedRange之后,遍历该Range对象中的所有行列。实际开发中,用第二种方法时发现了一个特别的现象,所以第二种方法也准备详细记述一下。
     
      第一步,打开Excel文档:

    object  filename = " " ;
    object  MissingValue = Type.Missing;
    string  strKeyWord = " " ;     // 指定要搜索的文本,如果有多个,则声明string[]
    Excel.Application ep = new  Excel.ApplicationClass();
    Excel.Workbook ew
    = ep.Workbooks.Open(filename.ToString(),MissingValue,
                MissingValue,MissingValue,MissingValue,
                MissingValue,MissingValue,MissingValue,
                MissingValue,MissingValue,MissingValue,
                MissingValue,MissingValue,MissingValue,
                MissingValue);

      然后准备遍历Excel工作表:

    Excel.Worksheet ews;
    int  iEWSCnt = ew.Worksheets.Count;
    int  i = 0 ,j = 0 ;
    Excel.Range oRange;
    object  oText = strKeyWord.Trim().ToUpper();
     
    for (i = 1 ;i <= iEWSCnt;i ++ )
    {
        ews
    =null;
        ews
    =(Excel.Worksheet)ew.Worksheets[i];
        oRange
    =null;
        (Excel.Range)oRange
    =((Excel.Range)ews.UsedRange).Find(
            oText,MissingValue,MissingValue,
            MissingValue,MissingValue,Excel.XlSearchDirection.xlNext,
            MissingValue,MissingValue,MissingValue);
        
    if (oRange!=null && oRange.Cells.Rows.Count>=1 && oRange.Cells.Columns.Count>=1)
        
    {
            MessageBox.Show(
    "文档中包含指定的关键字!","搜索结果",MessageBoxButtons.OK);
            
    break;
        }

    }

      这里要说两个值得注意的地方。一个是遍历工作表的索引,不是从0开始,而是从1开始;另外一个是Find方法的第六个参数SearchDirection,指定搜索的方向,帮助文档中说这个参数是可选项,但是我用MissingValue如论如何编译不能通过,不知什么原因,于是显式指定它的默认值xlNext。
     
      第一种方法实现了,再看看第二种方法。这种方法除了要遍历工作表,还要对工作表使用区域的行和列进行遍历。其它一样,只对遍历说明,代码如下:

    bool  blFlag = false ;
    int  iRowCnt = 0 ,iColCnt = 0 ,iBgnRow,iBgnCol;
     
    for (m = 1 ;m <= iEWSCnt;m ++ )
    {
        ews
    =(Excel.Worksheet)ew.Worksheets[m];
        iRowCnt
    =0+ews.UsedRange.Cells.Rows.Count;
        iColCnt
    =0+ews.UsedRange.Cells.Columns.Count;
        iBgnRow
    =(ews.UsedRange.Cells.Row>1)?
                        ews.UsedRange.Cells.Row
    -1:ews.UsedRange.Cells.Row;
        iBgnCol
    =(ews.UsedRange.Cells.Column>1)?
                        ews.UsedRange.Cells.Column
    -1:ews.UsedRange.Cells.Column;
     
        
    for(i=iBgnRow;i<iRowCnt+iBgnRow;i++)
        
    {
            
    for(j=iBgnCol;j<iColCnt+iBgnCol;j++)
            
    {
                strText
    =((Excel.Range)ews.UsedRange.Cells[i,j]).Text.ToString();
                
    if (strText.ToUpper().IndexOf(strKeyWord.ToUpper())>=0)
                
    {
                    MessageBox.Show(
    "文档中包含指定的关键字!","搜索结果",MessageBoxButtons.OK);
                }

            }

        }

    }

      显然这种方法比第一种繁琐得多,不过这里有一个关于遍历单元格的索引很特别的地方,当工作表中的使用区域UsedRange为单行单列的时候,对UsedRange中的单元格遍历起始索引值为1,为多行多列的时候,起始索引值为0,不知这是Excel程序设计者出于什么样的考虑?  
     
    展开全文
  • JAVA API文档,可以直接进行API搜索

    千次阅读 2013-05-27 16:09:25
    找了好久,终于找到一个好用的API参考文档,可以进行函数的搜索,有点像MSDN,目前感觉还不错。下面内容转载:http://www.javatang.com/javadoc 2006年06月5日 Java Doc Filed under: — Jet Ma @ 10:54 ...
  • 用C#实现Word文档搜索文本

    千次阅读 2007-03-22 00:18:00
    word应用程序中搜索和替换文本是举手之劳的事情,通过word的对象模型,我们也可以使用编程方式来实现。 Word的对象模型有比较详细的帮助文档,放在office安装程序目录,office 2003是Program Files/Microsoft...
  • LINUX超强归纳总结秘籍 [华为内部培训文档]

    千次下载 热门讨论 2012-12-11 08:40:46
    这个是网络上搜索到的,不知道有朋友上传没有,资料很完整,是华为内部linux资料,各命令,各种技巧都很全,归纳的很好,希望可以帮到大家! 高清文字,高含金量文档,高实用技巧,下载绝不忽悠 一共有4章: 1:...
  • Word文档在线怎么进行翻译

    千次阅读 2018-07-31 14:40:00
    我们工作的时候遇到的Word文档基本上是中文,但是如果外企工作的话,Word很有可能就会成英文或者其他国家的文字,如果我们想看得懂给你的Word文档,有两个方法,外语水平很好,还有一个方法就是进行翻译,多数人...
  • win10中书写markdown文档时,遇到右侧预览页面打不开的问题。在搜索解决办法的过程中,发现官方说从win8开始就有了这个问题了,解决办法就是安装Awesomium 1.6.6 SDK.但网友说该工具占用内存较大,且markdown...
  • 如何利用石墨文档进行团队协作

    千次阅读 2020-04-15 23:04:15
    目录开始使用石墨文档团队协作创建团队空间并邀请协作伙伴加入协作编辑创建文档批注 开始使用石墨文档 打开石墨文档官网 点击右上角“进入石墨” 根据提示注册石墨文档账号 团队协作 创建团队空间并邀请协作伙伴...
  • word文档自动答题搜索

    千次阅读 2018-12-31 14:49:00
    word文档自动答题搜索 安装模块: pip install python-docx 代码: import os import webbrowser import docx import time def baidu(que): url = "https://www.baidu.com/s?wd=" +que webbrowser.open...
  • 如何创建可搜索的PDF文档

    千次阅读 2017-10-27 10:01:12
    创建可搜索的PDF文档,目前主要有两种方法:一是利用精益的可搜索PDF数字化解决方案直接将纸质文件转成可搜索的PDF文档,另一种则是利用专业的制作软件来执行,这些软件主要是利用光学文字识别(OCR)技术来达成转换...
  • 换一种思路,其实这个工具也是一个很好的网络情报监控工具,我们可以用它来监控公司信息外网的发布情况。如何利用谷歌快讯监控公司信息外网的发布情况呢?1. 首先需要注册一个谷歌账号用于接收谷歌快讯的内容。...
  • 高通文档搜索方法

    千次阅读 2018-08-23 15:39:35
    =====&gt;Documents ====&gt;Software Documents =====&gt;Software Product MSM8996.LA.2.0.2 Standard OEM CSP =====&gt;点击选择即可  
  • 国内外主流文档搜索网站

    千次阅读 2014-05-15 09:28:33
    当今社会,搜索引擎已经成为我们从网络获取知识的主要通道,专门面向文献文档资料的搜索网站让我们更轻易的找到我们所需的论文、报告、申请书等等资 料,下面是一些国内外主要的文档搜索引擎。   国内文档...
  • Java jdk 在线文档(可搜索类)

    千次阅读 2018-07-12 17:30:46
    java 1.6 帮助文档中文链接:http://download.csdn.net/detail/qw599186875/9608735英文Java1.8 帮助文档英文中文 – 谷歌版在线版: https://blog.fondme.cn/apidoc/jdk-1.8-google/下载链接:...
  • Elasticsearch搜索引擎第七篇-文档管理

    千次阅读 2018-11-17 17:04:52
    文章目录新建文档获取文档获取单个文档获取多个文档 新建文档 新增文档,自动生成文档id: POST twitter/_doc/ { &amp;amp;quot;id&amp;amp;quot;: 1, &amp;amp;quot;user&amp;amp;quot; : &...
  • MFC使用OpenCV在文档窗口中显示图像(支持多格式图片),VS2010中新建一个 MFC单文档或多文档的应用程序,结合OpenCV强大的图像处理工具,我们可以MFC的“File/open”直接打开并显示图像,具体方法如下: ...
  • 如何更好的进行项目文档管理 在文档管理的过程中,需要把握住一些重要的原则和方法,这样可以让我们的文档真正达到我们预期的目的。 文档模板的管理 面对各类纷繁复杂的文档,如果各式各样,每个人一个风格,不论...
  • 引言 有时候你会遇到这种情况:昨晚花了N个小时精心准备明天演讲的Word,亦或者是花了大量...今天给大家说的这个软件就是一个免费搜索工具Anytxt,全称是AnyTXT Searcher,各种Office文档,文本文件,代码,PDF等,...
  • Elasticsearch 7提供了多种检索文档的方式,我们可以通过Restful API的方式来搜索索引中的文档。Elasticsearch的搜索可以分为以下几个类型: 全文搜索 词项搜索 复合搜索 嵌套搜索 位置搜索 特殊搜索 1 全文搜索 ...
  • 接口文档

    千次阅读 2017-04-09 23:07:45
    项目开发中,web项目的前后端分离开发,APP开发,需要由前后端工程师共同定义接口,编写接口文档,之后大家都根据这个接口文档进行开发,到项目结束前都要一直维护。 二、为什么要写接口文档? 1、项目开发过程...
  • 朴素想法用户输入一个查询query,query由若干词(term)组成,文档也由若干词(term)组成。那么怎么评判查询和文档的相关性的高低。很朴素简单的想法就是文档中包含的term与查询query中包含的term,两者越多相同的...
  • layuiadmin开发文档

    万次阅读 多人点赞 2019-04-28 11:13:24
    layuiAdmin pro v1.x 【单页版】开发者文档 更新日志常见问题在线演示会员专区切换到:iframe版文档 layuiAdmin pro (单页版)是完全基于 layui 架构而成的后台管理模板系统,可以更轻松地实现前后端分离,它...
  • 现在用help and manaual 制作了cmh文档,虽然能够有目录,索引和超链接,但是,无法实现搜索在搜索处输入文字,都是显示,找不到主题。不知道这是为什么?请大家帮帮我,告诉我如何实现这个功能,或者推荐我其他...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 660,066
精华内容 264,026
关键字:

如何在文档内进行搜索