当前位置: 首页 > news >正文

网站自动化锚文本的实现逻辑

锚文本,‌即超链接的文本部分,‌它在网页中扮演着至关重要的角色。‌通过点击锚文本,‌用户可以方便地在网页间进行跳转,‌从而极大地提升了用户体验。‌同时,‌在搜索引擎优化(‌SEO)‌领域,‌锚文本也发挥着不可忽视的作用。‌搜索引擎会通过分析锚文本的内容,‌来判断链接页面的主题和相关性,‌进而影响页面的排名。‌因此,‌合理地设置锚文本,‌对于提升网站的SEO效果具有重要意义。‌

自动化锚文本实现的背景和需求

随着网站内容的不断增多,‌手动设置锚文本变得愈发繁琐和耗时。‌为了提高工作效率,‌减少人力成本,‌自动化锚文本的实现成为了迫切的需求。‌通过自动化手段,‌可以快速地生成大量的锚文本,‌提高网站的内链建设效率,‌进而提升网站的SEO效果。‌

锚文本的收集

在实现自动化锚文本之前,‌首先需要收集网站中的文本内容。‌下面以安企CMS的自动化锚文本功能为例,‌介绍锚文本的收集策略。‌

安企CMS提供了自动提取锚文本和手动提取锚文本两种收集锚文本的方式。如果选择了自动提取锚文本,那么程序就会在用户添加文章的时候,自动解析文章的关键词,并将关键词自动添加为当前文章的锚文本。手动处理的话,则提供了逐个关键词填写以及批量导入关键词的两种方式。
请添加图片描述

自动化锚文本的策略

制定自动化锚文本的策略是关键步骤之一。‌这包括确定锚文本的生成规则,‌如关键词的选择、‌锚文本的长度、‌出现的位置等。
请添加图片描述

  • 自定义锚文本密度
    安企CMS在处理锚文本的生成策略时,‌提供了自定义锚文本密度的选项,用户可以自主选择锚文本的密度。

  • 按关键词由长到短匹配
    安企CMS采用了长度优先的策略,就是说,如果内容中不同锚文本,优先使用长度最长的锚文本。内容里出现AAB这样的关键词时,锚文本会给AAB,而不是AA,或AB

  • 仅匹配一次
    如果文章中有多个相同的锚文本关键词,则只给第一个关键词添加上锚文本,而后续的关键词只进行加粗处理,保证一个内容里同一个关键词锚文本仅出现一次,同一个URL也只做一次锚文本,其它的则会加粗显示。

  • 锚文本生成方式
    安企CMS采用了长度优先的策略。就是说,如果有相同链接的不同锚文本,优先使用长度最长的锚文本。如果文章中有多个相同的锚文本关键词,则只给第一个关键词添加上锚文本,而后续的关键词只进行加粗处理。

安企CMS采用了自动插入关键词以及手动批量更新关键词两种方式,如果选择了自动插入关键词,则会在发布文章的时候,自动将文章中合适的关键词用锚文本来替代,实现锚文本的生成。如果选择了手动批量更新关键词,则会在锚文本页面中,提供批量更新锚文本的功能,用户可以按照自己的需求,手动更新锚文本。

自动化锚文本的实现代码

说明:由于安企CMS 使用的是 GoLang 开发,因此以下代码为 GoLang 语言的实现方式。

func AutoInsertAnchors(anchors []*model.Anchor, content string, link string) string {if len(anchors) == 0 {//没有关键词,终止执行return ""}//获取纯文本字数stripedContent := library.StripTags(content)contentLen := len([]rune(stripedContent))// 获取锚文本密度if PluginAnchor.AnchorDensity < 20 {//默认设置200PluginAnchor.AnchorDensity = 200}// 判断是否是Markdown,如果开头是标签,则认为不是MarkdownisMarkdown := falseif !strings.HasPrefix(strings.TrimSpace(content), "<") {isMarkdown = true}//计算最大可以替换的数量maxAnchorNum := int(math.Ceil(float64(contentLen) / float64(PluginAnchor.AnchorDensity)))// 定义一个替换结构体,用于存储替换的内容type replaceType struct {Key   stringValue string}// 记录已存在的关键词和链接existsKeywords := map[string]bool{}existsLinks := map[string]bool{}var replacedMatch []*replaceTypenumCount := 0//所有的a标签计数,并临时替换掉,防止后续替换影响reg, _ := regexp.Compile("(?i)<a[^>]*>(.*?)</a>")content = reg.ReplaceAllStringFunc(content, func(s string) string {reg := regexp.MustCompile("(?i)<a\\s*[^>]*href=[\"']?([^\"']*)[\"']?[^>]*>(.*?)</a>")match := reg.FindStringSubmatch(s)if len(match) > 2 {existsKeywords[strings.ToLower(match[2])] = trueexistsLinks[strings.ToLower(match[1])] = true}key := fmt.Sprintf("{$%d}", numCount)replacedMatch = append(replacedMatch, &replaceType{Key:   key,Value: s,})numCount++return key})//所有的strong标签替换掉reg, _ = regexp.Compile("(?i)<strong[^>]*>(.*?)</strong>")content = reg.ReplaceAllStringFunc(content, func(s string) string {key := fmt.Sprintf("{$%d}", numCount)replacedMatch = append(replacedMatch, &replaceType{Key:   key,Value: s,})numCount++return key})// 匹配 Markdown 格式的锚文本,同时要考虑别替换掉图片// [keyword](url)reg, _ = regexp.Compile(`(?i)(.?)\[(.*?)]\((.*?)\)`)content = reg.ReplaceAllStringFunc(content, func(s string) string {match := reg.FindStringSubmatch(s)if len(match) > 2 && match[1] != "!" {existsKeywords[strings.ToLower(match[2])] = trueexistsLinks[strings.ToLower(match[3])] = true}key := fmt.Sprintf("{$%d}", numCount)replacedMatch = append(replacedMatch, &replaceType{Key:   key,Value: s,})numCount++return key})// Markdown 格式的加粗// **Keyword**reg, _ = regexp.Compile(`(?i)\*\*(.*?)\*\*`)content = reg.ReplaceAllStringFunc(content, func(s string) string {key := fmt.Sprintf("{$%d}", numCount)replacedMatch = append(replacedMatch, &replaceType{Key:   key,Value: s,})numCount++return key})//过滤所有属性,防止在自动锚文本的时候,会将标签属性也替换reg, _ = regexp.Compile("(?i)</?[a-z0-9]+(\\s+[^>]+)>")content = reg.ReplaceAllStringFunc(content, func(s string) string {key := fmt.Sprintf("{$%d}", numCount)replacedMatch = append(replacedMatch, &replaceType{Key:   key,Value: s,})numCount++return key})if len(existsLinks) < maxAnchorNum {//开始替换关键词for _, anchor := range anchors {if anchor.Title == "" {continue}if strings.HasSuffix(anchor.Link, link) {//遇到当前url,跳过continue}//已经存在存在的关键词,或者链接,跳过if existsKeywords[strings.ToLower(anchor.Title)] || existsLinks[strings.ToLower(anchor.Link)] {continue}//开始替换replaceNum := 0replacer := strings.NewReplacer("\\", "\\\\", "/", "\\/", "{", "\\{", "}", "\\}", "^", "\\^", "$", "\\$", "*", "\\*", "+", "\\+", "?", "\\?", ".", "\\.", "|", "\\|", "-", "\\-", "[", "\\[", "]", "\\]", "(", "\\(", ")", "\\)")matchName := replacer.Replace(anchor.Title)reg, _ = regexp.Compile(fmt.Sprintf("(?i)%s", matchName))content = reg.ReplaceAllStringFunc(content, func(s string) string {replaceHtml := ""key := ""if replaceNum == 0 {//第一条替换为锚文本if isMarkdown {replaceHtml = fmt.Sprintf("[%s](%s)", s, anchor.Link)} else {replaceHtml = fmt.Sprintf("<a href=\"%s\" data-anchor=\"%d\">%s</a>", anchor.Link, anchor.Id, s)}key = fmt.Sprintf("{$%d}", numCount)//加入计数existsLinks[anchor.Link] = trueexistsKeywords[anchor.Title] = true} else {//其他则加粗if isMarkdown {replaceHtml = fmt.Sprintf("**%s**", s)} else {replaceHtml = fmt.Sprintf("<strong data-anchor=\"%d\">%s</strong>", anchor.Id, s)}key = fmt.Sprintf("{$%d}", numCount)}replaceNum++replacedMatch = append(replacedMatch, &replaceType{Key:   key,Value: replaceHtml,})numCount++return key})//判断数量是否达到了,达到了就跳出if len(existsLinks) >= maxAnchorNum {break}}}//关键词替换完毕,将原来替换的重新替换回去,需要倒序for i := len(replacedMatch) - 1; i >= 0; i-- {content = strings.Replace(content, replacedMatch[i].Key, replacedMatch[i].Value, 1)}// 返回替换后的内容return content
}

http://www.mrgr.cn/news/1677.html

相关文章:

  • 【C++ 面试 - 面向对象】每日 3 题(一)
  • 【ubuntu24.04】错误:8llvm 由于没有公钥:无法验证下列签名 NO_PUBKEY
  • 软考软件设计师-备考须知
  • 恒创科技:云服务器的备份和快照哪个更好?
  • Python抓取远程图片到本地
  • 05--kubernetes组件与安装
  • python爬虫代理IP实战
  • 安卓中携程和线程的区别。携程是指什么?
  • 余弦相似度详解及应用案例
  • DNS域名解析服务
  • 基于Spring boot的名城小区物业管理系统
  • 物联网中的物模型用大白话举例子一句话讲清楚,作用,原理。这东西我认为不咋好用,不过多少有点用。
  • 引领能源新时代:打造智能化加油系统新纪元
  • 计算机网络——TCP协议与UDP协议详解(上)
  • 网络原理知识总结
  • volatitle-线程并发-小白一文速通
  • 智能Java开发工具IntelliJ IDEA v2024.2全新发布——更好支持Spring开发
  • 面试官:谈谈你对Shadow DOM的理解
  • MySQL 数据库经验总结
  • 想学接口测试,不知道那个工具适合?