首页 > 其他分享 >网站自动化锚文本的实现逻辑

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

时间:2024-08-20 22:24:31浏览次数:9  
标签:逻辑 string 关键词 content replacedMatch key 自动化 文本

锚文本,‌即超链接的文本部分,‌它在网页中扮演着至关重要的角色。‌通过点击锚文本,‌用户可以方便地在网页间进行跳转,‌从而极大地提升了用户体验。‌同时,‌在搜索引擎优化(‌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 {
		//默认设置200
		PluginAnchor.AnchorDensity = 200
	}

	// 判断是否是Markdown,如果开头是标签,则认为不是Markdown
	isMarkdown := false
	if !strings.HasPrefix(strings.TrimSpace(content), "<") {
		isMarkdown = true
	}
	//计算最大可以替换的数量
	maxAnchorNum := int(math.Ceil(float64(contentLen) / float64(PluginAnchor.AnchorDensity)))
  // 定义一个替换结构体,用于存储替换的内容
	type replaceType struct {
		Key   string
		Value string
	}
  // 记录已存在的关键词和链接
	existsKeywords := map[string]bool{}
	existsLinks := map[string]bool{}

	var replacedMatch []*replaceType
	numCount := 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])] = true
			existsLinks[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])] = true
			existsLinks[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 := 0
			replacer := 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] = true
					existsKeywords[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
}

标签:逻辑,string,关键词,content,replacedMatch,key,自动化,文本
From: https://blog.csdn.net/no_reg/article/details/141335313

相关文章

  • 机器学习:逻辑回归--下采样
    目录前言一、为什么使用下采样1.例如:2.导致:3.办法:4.结果:二、代码实现1.完整代码2.导入库3.可视化混淆矩阵4.导入数据5数据预处理6.下采样7.取出训练集和测试集8.建立模型9.进行测试总结前言        下采样(Downsampling)是一种在数据处理中减少样本......
  • Swift文档生成工具全攻略:从代码到文档的自动化之旅
    标题:Swift文档生成工具全攻略:从代码到文档的自动化之旅在Swift开发的世界中,代码的清晰表达与高效维护同等重要。Swift的代码文档生成工具,如同一盏明灯,照亮了代码的内在逻辑,让其他开发者或未来的你能够快速理解和使用你的代码。本文将带你深入了解如何在Swift中使用文档生成......
  • B2B进销存ERP后台管理系统的逻辑架构与设计,AxureRP原型产品经理实战案例
    模块分析:进销存系统是一种用于企业管理库存、销售和采购活动的信息系统。它的主要作用包括但不限于以下几个方面:1.库存管理实时库存跟踪:准确记录每种商品的库存数量,确保数据的实时性和准确性。库存预警:当库存量低于预设的安全水平时自动发出警报,防止缺货或积压。先进先出(......
  • 一个AI原生数据应用数据库开发框架,专为数据3.0时代设计,支持私域问答、多数据源交互、
    前言在数字化转型的浪潮中,企业在数据处理和分析方面面临着巨大的挑战。传统软件往往存在复杂的数据库交互、低效的数据整合流程以及缺乏智能化数据分析能力等痛点。这些问题不仅拖慢了企业决策的步伐,也限制了创新的发展。因此,急需一款能够简化数据库交互、智能化数据处理的软......
  • [题解]P4052 [JSOI2007] 文本生成器
    P4052[JSOI2007]文本生成器正难则反,我们发现用总字符串个数\(26^m\),减去不可读的字符串个数,就是答案。要使一个字符串不可读,就不能让任何模式串在其中出现。如果某个主串的第\(i\)位与自动机的节点\(j\)相匹配,那么如果状态\(j\)包含模式串(即有一个前缀是一个模式串),那么不管主......
  • 【机器学习-监督学习】逻辑斯谛回归
    【作者主页】FrancekChen【专栏介绍】⌈⌈⌈Python机器学习⌋......
  • WPF中的视觉树(VisualTree)和逻辑树(LogicalTree)
    可视化树和逻辑树我们先来理解一下什么是可视化树和逻辑树。通俗点来说,可视化树就是在XAML中定义的或者代码添加的元素组成的树。就像下面这样1<Grid>2<ButtonHorizontalAlignment="Center"VerticalAlignment="Center"Content="点击我"Click="Button_Click"><......
  • 逻辑运算符
    逻辑运算符&&||!packageoperator;/***@version:javaversion1.8*@Author:MrTheroux*@description:*@date:2024-08-209:33*/publicclassDemo05{publicstaticvoidmain(String[]args){booleana=true;booleanb......
  • 怎样提高写作效率?AI工具集,自动化辅助,省时高效。
    迈入2024年,难道仍有人不谙熟AI写作之道吗?诸如日常繁琐的工作汇报、总结等任务,借助AI写作工具,便能迅速完成,有效解决了我们的棘手工作。当然,优质的AI写作工具能够创作出更高水准的文章,诸如学术论文、小说、营销策划案……在此,我并不打算对ChatGPT、文心一言等大型语言模型进行......
  • ansible自动化之playbook剧本【nginx安装为例】
    一、简介roles则是ansible中,playbooks的目录组织结构。将代码或者文件进行模块化,成为roles的文件目录组织结构,易管理,易理解,代码可重用,层次清晰。二、准备目录结构创建所需目录:mkdir-proles/nginx/{files,handlers,tasks,templates,vars}创建所需文件:touchroles/......