网页内容相似度检测算法——Go

基于业务需要,记录由Go实现的网页内容相似度检测算法
算法思想参考:一种通用的网页相似度检测算法

作者使用JAVA实现,这里用Go复现一遍~


一、提取网页文本

为方便记录网页信息,写一个 WebPage 类型:

type WebPage struct {
	url     string
	title   string
	content string
}

网页标题及内容爬取借助工具chromedp("github.com/chromedp/chromedp"):
ps:chromedp的源码阅读 蠢作者还在龟速更新。。。

// GetWebPage 提取网页文本
func GetWebPage(url string) WebPage {
	// create context
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// run task list
	var res string
	var title string
	err := chromedp.Run(ctx,
		chromedp.Navigate(url),
		chromedp.Title(&title),
		chromedp.Sleep(1*time.Second),
		chromedp.WaitVisible(`body`, chromedp.ByQuery),
		chromedp.InnerHTML(`body`, &res, chromedp.ByQuery),
	)
	if err != nil {
		log.Fatal(err)
	}

	//log.Println(strings.TrimSpace(title))
	//log.Println(strings.TrimSpace(res))

	return WebPage{
		url:     url,
		title:   title,
		content: res,
	}
}

二、文本分词

学习大家用Go编写的分词器,测试了 Segogse ,后者是前者和 jieba 的改进,后者字典更全!接下来我们就用gse来分词:

var (
	seg    gse.Segmenter
	posSeg pos.Segmenter
)
func score(webPage1, webPage2 WebPage) float64 {
	// 加载默认词典
	seg.LoadDict()
	posSeg.WithGse(seg)
	//分词
	webPage1Words := posSeg.Cut(webPage1.title+"\n"+webPage1.content, true)
	webPage2Words := posSeg.Cut(webPage2.title+"\n"+webPage2.content, true)
	//去掉空格及标点
	webPage1Words = posSeg.TrimWithPos(webPage1Words, "x")
	webPage2Words = posSeg.TrimWithPos(webPage2Words, "x")
	//词频统计
	webPage1WordsFre := frequence(webPage1Words)
	webPage2WordsFre := frequence(webPage2Words)
	//输出详细信息
	//fmt.Println(webPage1WordsFre)
	//fmt.Println(webPage2WordsFre)
	//使用简单共有词判定
	return simpleScore(webPage1WordsFre, webPage2WordsFre)
}

使用的是带pos标志的Cut输出,这是为了方便我们去除一些不必要的输出。观察输出信息,可以发现空格、符号一般都输出x,因此我们使用TrimWithPos方法截去所有pos为x的词组。

整理分词后就可以网页相似度比对了!等等,做词频统计可以降低之后词组比对的工作量。

三、词频统计

直接用map,既可以保证键唯一性,又可以统计词频:

// 词频统计
func frequence(words []gse.SegPos) map[string]int {
	var fre map[string]int
	fre = make(map[string]int)
	for _, word := range words {
		text := word.Text
		fre[text]++
	}
	return fre
}

四、网页内容相似度检测

一般来说,相似度分值超过 0.5 的就被视为 这两个网页拥有相同的内容

参考的算法思想作者表示,可以通过 计算词向量的余弦相似度判定简单共有词 来实现目的,但蠢作者没看懂余弦相似度算法/(ㄒ…ㄒ)/~~(求大神指教…),这里展出用简单共有词判定相似性的方法:

// 简单共有词判定相似性
func simpleScore(webPage1WordsFre, webPage2WordsFre map[string]int) float64 {
	res := 0
	//判断有几个相同的词
	for key, _ := range webPage1WordsFre {
		if webPage2WordsFre[key] > 0 {
			res++
		}
	}
	log.Println("网页1有的词数:", len(webPage1WordsFre))
	log.Println("网页2有的词数:", len(webPage2WordsFre))
	log.Println("网页1和2共有的词数:", res)
	webScore := float64(res) / math.Min(float64(len(webPage1WordsFre)), float64(len(webPage2WordsFre)))
	log.Println("相似度分值 =", webScore)
	return webScore
}

最后验证一下就行啦~

func IsSimilar(url1, url2 string) bool {
	return similarScore(url1, url2) >= 0.5
}

func main() {
	similar := IsSimilar(`https://pkg.go.dev/crypto/rand`, `https://pkg.go.dev/math/rand`)
	if similar {
		fmt.Println("两个网页拥有相同的内容")
	} else {
		fmt.Println("两个网页拥有不同的内容")
	}
}

结果如下:
相似度
显然Go官方的两个rand算法网页非常相似~


【不断进取,继续探索】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值