您的位置 首页 seo优化

SEO采集海量文章,用倒排索引找出"类似的标题"

截止目前为止,站群的模式依然是有效的,运用站群的方式截取海量搜索流量偷偷变现再正常不过。一个人管理一批网站,内…

截止目前为止,站群的模式依然是有效的,运用站群的方式截取海量搜索流量偷偷变现再正常不过。一个人管理一批网站,内容的更新离不开采集。本文使用倒排索引的逻辑解决SEO采集场景中”标题类似”的问题,顺便带入一个小算法,过段时间会结合这个小算法分享一个”重要热点自动推送到微信”的案例。倒排索引是搜索引擎检索的基石,理解倒排索引有助于了解搜索引擎的排序逻辑,很多做SEO的朋友甚至不知道基本的排序规则,不能把这些规则结合到日常优化,做SEO全凭感觉。我在文章中偶尔出现的一些技术细节、小思路,表面上看起来离赚钱很远,但实际上正是这些小东西支撑起一个人的判断力,机会来的时候才能做正确的选择。每个SEOer都指导过或者自己干过采集这个事,因为网站内容的数量和质量对于流量的提升至关重要。在早几年PC时代,自媒体这个概念还没有盛行,一个网站的内容生产如果全靠公司编辑组的几个同学们,很可能撑不到自己被辞退的那天。那时候版权和原创的概念还很模糊,一个网站20%的内容是原创,80%的内容是采集,我觉得已经是业界良心了,网站内容互相采集是业内常态,绝大部分个人站长的网站内容从第一篇开始采起。2016年我在看完市面上的大部分采集工具后(那时候普遍是火车头,好像现在也是),我用自己为数不多的产品思维嫌弃了一下,索性用Python开发了一个采集工具:时隔四年有些感慨,人越缺少什么就越爱炫耀什么,自己技术烂,特别是英语死烂,所以设计界面的时候特意要把相关字段和标题用英文表示,现在看起来眼睛很辣。但是这个工具的功能直到现在我依然不觉得过时,我曾在曹政老师的公众号下评论过,自己是个喜欢动脑不喜欢动手的人,重复的事情让我反复操作10次8次我就得考虑能不能自动化,要不然会开始烦躁。为什么那会嫌弃市面上的采集工具,因为我按照他们的流程走了一遍,我发现过程中很不灵活,不够全面。我希望这个工具打从它做好之后,我就不需要再考虑任何问题,只需要按部就班即可,所有可能发生的情况我都尽可能的设计到里面。这个工具可以对接主流的三大开源内容管理系统:dedecms、phpcms、ecms,接口是自己写的,整体模型是这样:以己方网站为一级目录,目录里包含多个目标采集网站作为二级目录,每个采集网站里又包含多个栏目,每个栏目下存储各自采集规则和历史记录,常态下一天入库几万是没有问题的。程序支持:随时切换己方运营的不同网站,自动调出事先设定的目标网站和规则。每个目标网站的采集规则,支持增删改查、保存、导入导出。单一目标可设定多套规则方案,根据页面自动识别最优抓取规则。html格式化(保留原文段落的同时去除别人的所有HTML标签)特定字符替换、特定规则的字符替换(正则),图片提取及链接补全。按网站、栏目轮番采集,定时定量,自动判重,自动入库,等待审核。说到判重,就到了我们今天的主题:”类似标题”的判重问题。当你把程序打开时,它开始工作,从你为它配置的各个网站抓取内容,这相当于全网采集,目标网站自身和目标网站之间都有可能碰到文章重复的情况。在一个网站里一样的文章除了技术或人为出现问题,一般都是一样的链接,所以只要让程序判断链接是否一模一样即可,这很简单。http://www.a.com 和 http://www.a.com一模一样不入库,但是在不同的网站里,由于大家都是采来采去,很可能采集一模一样的文章,将多篇标题一样正文也一样的文章一起发布在网站上,从优化的角度来说是不可取的,特别是采集情况下,长期自动化采集,没有人工干预,久而久之会积累大量重复性内容,那网站离死不远了。因此除了初步的链接判断之外,还要加入标题的判断,不管是一个网站内部还是网站与网站直接,但凡想入库都要做判断。标题如果完全一样,处理方式则跟链接一样,直接丢弃即可,可麻烦的问题在于:标题类似。假设目前网站里有这样10篇文章,它们的标题分别是(拿微博热搜举个例子):四字弟弟把沙发借蔡国庆坐坐呗特朗普团队称出现死人票美队回应与拜登撞脸阿云嘎可以把钢琴借给蔡国庆躺李栋旭给孔刘送咖啡车应援拜登称特朗普拒绝承认选举结果令人尴尬专家建议女性退休年龄延至55岁你最后网购的那个东西拥有了2万倍生育对女性职业生涯的影响日本首相菅义伟欲率先会见拜登这个时候程序采集抓取了一篇文章,它的标题是:拜登称特朗普拒绝承认选举结果使人尴尬它和现有数据库里的一条标题是一个意思,阐述的是一件事情,标题几乎一模一样,文章正文则完全一样,只是编辑把标题中的”令人”换成了”使人”。如果我们让程序自动去判断两条标题是否一样,那对于不是0就是1的计算机它给的结果就是:否。但我们显然不能让这样的文章再入库,因此要有合适的办法来处理,让程序能识别出来,同时我们网站数据库里可能有几百几千万甚至更多的标题,这个办法有效的前提还得考虑效率,不能做一次判断要几秒。在那段时间我也是不得其所,网上的工具没有发现能处理这个问题的,都是完全一样就丢弃,一字之差也认为是不一样的文章。过了一段时间在搜索引擎书籍里了解到了”倒排索引”的思路,真是惊为天人,当下就想到可以用来解决这个问题。我们思考一下:百度或谷歌为什么可以在几毫秒之内搜索到我们需要的内容?这里面其实有很多技术方案在支撑,但一切的方案都建立在”倒排索引”的前提之下,是”倒排索引”使得”搜索”这一行为极大提升检索效率的同时并附有一定的相关性。倒排索引:假设这是我们的数据库,文档就是一个网页或者一篇文章,我们这里用标题表示,当用户搜索:特朗普因为没有一模一样的(一模一样的瞬间可以找到),数据库就一条条的检索,把包含特朗普的文档对应的ID拿出来,可得:2、6,这样我们就找到了用户需要的相关内容。可如果这里面有100亿条数据,这样的方式不知道要查到猴年马月,这个时候我们多建一份这样的表:如图,我们给单词新建另一份表,表里每个词是唯一的,每个词有哪些文档包含它,把ID都列出来。当用户搜索:特朗普与拜登,搜索引擎分词:特朗普、拜登根据第二张表,特朗普这个关键词显示涉及到它的有:2、6,拜登这个关键词则是:3、6还记得初中学过的交集吧:2、6和3、6取交集,共同的是6,因此本次检索找出来的相关内容就是:文档6,这个文档即包含特朗普也包含拜登,满足了基本的相关性。文章可能有千千万万,但是世界上的词汇量始终是有限的,而且只要是一模一样的,数据库可以马上搜索出来。不管第一张表里有多少亿数据,通过第二张表我们可以瞬间找到包含目标关键词的所有文档ID,取交集后再用文档ID去第一张表里直接取,不需要一条条的查。这第二张表就是:倒排索引,又称反向索引。至于所谓的正排索引,我感觉也没有这个概念,它只是有了倒排后相对的而已。在当时了解到这个思维后,我是真感慨,在最开始的时候人家到底是怎么想出来的,太佩服了。这个应用是针对文档(文章),在我看完之后,我在想:是否可以把文章换成标题,利用这个思路来判断标题是否极度类似?如果你已经有了初步的思路,那说明倒排索引的思想已经理解了。说一下技术细节:会碰到这个问题并且在考虑解决方案的人,肯定是会技术的人,因此简单给一下核心代码,用Python实现,其实就是dict的设计,这个过程还会涉及到搜索结果的初步得分计算,SEO的朋友如果不会的话也一起了解看看。刚才是为了方便理解倒排索引,所以用一个简单的例子讲解它是怎么为我们的搜索工作,实际上在搜索引擎检索数据时,并非简单的把所有文档ID拿出来取交集,这会存在有很大问题。这块是比较专业的知识,我自己也不算深入理解,仅仅只是依靠这些思维来解决业务问题而已,有兴趣的朋友可以看这本书:《这就是搜索引擎-核心技术详解》PS:感谢SEO业内大神ZERO的各种分享,我早期在他的文章里得到很多帮助和提升!在建立了倒排索引之后,当用户搜索时,一般会有以下几个检索逻辑:一次一文档一次一单词结合一次一文档的跳跃指针一次一文档的本质就是取交集的逻辑,我们这里使用相对简单的一次一单词的方式。搜索:特朗普与拜登特朗普,对应包含它的所有文档ID是:1、2、3拜登,对应文档ID是:3,4,5取出特朗普,1,2,3各得一分再取出拜登,1,2,4,5各得一分,3累积得两分因此文档3是最具相关性的,这就是一次一单词的逻辑,最终我们就得到了每个相关文档的相似性得分,从大到小罗列就是一次搜索的初步排序了。我们其实是把文档出现次数叠加计算得分,在实际的检索中,得分并非简单这样计算,每个文档要结合很多因素单独计算得分,然后再叠加,但是仅用来处理我们的问题是足够了。核心代码:# 存储历史入库的所有标题,相当于表1seen_title ={ ‘1’:[‘拜登称特朗普拒绝承认选举结果令人尴尬’],’2′:[‘特朗普团队称出现死人票’]
}
# 把标题对应分词单独建表,方便提取(与表1同步更新)
title_word ={ ‘1’:[‘拜登’,’特朗普’,’拒绝’,’承认’,’选举’,’结果’,’令人’,’尴尬’],’2′:[‘特朗普’,’团队’,’出现’,’死人票’]
}
# 表2,单词对应的所有包含它的标题ID(与表1同步更新)
word_id ={ ‘特朗普’:set([‘1′,’2′,’3′]),’拜登’:set([‘3′,’4′,’5’])
}
# 求余弦值
defcount_cos(new_word,old_word):
return cos# 计算相关性得分
defget_doc_id(title):
# defaultdict创建的整数型字典,存储文档得分 id_count = defaultdict(int) # 存储本次新增标题的所有分词 new_word =[word.encode(‘utf-8’)for word,flag in pg.cut(title)]
# 循环提取每个单词对应的所有文档ID并计算得分
for word in new_word: # 数据库里没有记录的单词忽略计算 if word notin word_id:continue for ids in word_id[word]:id_count[ids]+=1
# 最终得到所有文档的最终得分,降序 id_count = sorted(id_count.items(),key=lambda x:x[1],reverse=True) # 取得分最高的与本次标题计算余弦值,大于目标值就算类似重复,反之其他的相似度更低,不必计算 return count_cos(new_word,title_word[id_count[0][0]])>=0.8get_doc_id(title)

本文来自网络,不代表半米科技立场,转载请注明出处:https://www.banmikeji.com/10838.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

返回顶部