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

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

作者: Fesion | 来源:发表于2024-08-18 21:25 被阅读0次

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

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

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

锚文本的收集

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

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


anchor1.png

自动化锚文本的策略

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


anchor2.png
  • 自定义锚文本密度
    安企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
}

相关文章

网友评论

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

      本文链接:https://www.haomeiwen.com/subject/tyapkjtx.html