Go 简单实现根据网址爬取整站URL(Go爬虫,生成sitemap.xml)


想要实现一个根据一个网站的域名,然后把整个网站的所有链接都爬取出来,以前都是Python爬取,突发奇想用Go也来弄一个,借鉴网上很多资料。整理了一个可以实现的功能,有兴趣的同学可以试试。


package main

import (
	"flag"
	"fmt"
	"regexp"
	"time"

	"github.com/PuerkitoBio/goquery"
	"github.com/douyacun/gositemap"
	"github.com/gocolly/colly"
	"github.com/gocolly/colly/extensions"
)

var priority float64 = 1

func main() {
	//命令参数获取
	targetUrl := flag.String("url", "", "目标站点地址")
	path := flag.String("path", "", "目标站点地址")
	Parallelnum := flag.Int("parallel", 500, "并发数")
	Delay := flag.Int("delay", 0, "延迟(毫秒)")
	MaxLinks := flag.Int("maxlink", 50000, "最大链接数")

	//[必须调用]:从 arguments 中解析注册的 flag,不然参数获取都没值
	flag.Parse()

	//参数验证
	if len(*targetUrl) == 0 {
		panic("请传递目前站点地址")
	}
	if len(*path) == 0 {
		*path = fmt.Sprintf("gositemap/%s/", time.Now().Format("20060102_150405"))
	}

	st := gositemap.NewSiteMap()
	st.SetDefaultHost(*targetUrl)
	st.SetPretty(true)
	// 每个sitemap文件不能多于50000个链接,这里可以自己配置每个文件最多,如果超过MaxLinks,会自动生成sitemap_index.xml文件
	st.SetMaxLinks(*MaxLinks)
	//xml文件输出地址
	st.SetPublicPath(*path)

	t := time.Now()
	number := 1
	//初始化 创建收集器
	c := colly.NewCollector(func(c *colly.Collector) {
		extensions.RandomUserAgent(c) // 设置随机头
		c.Async = true
	},
		//过滤url,去除外链
		colly.URLFilters(
			//regexp.MustCompile("^(https://www\\.uppdd\\.com/)"),
			regexp.MustCompile("^("+*targetUrl+"/(.*))"),
		),
	)
	//控制下速度
	c.Limit(&colly.LimitRule{
		//DomainGlob:  "*uppdd.*", //过滤规则的作用域,不限制则全部链接皆使用该规则
		DomainGlob:  "*",
		Parallelism: *Parallelnum,
		Delay:       time.Duration(*Delay),
	})
	// 响应的格式为HTML,提取页面中的链接
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		link := e.Attr("href")
		href := e.Request.AbsoluteURL(link)
		// 访问url  内部会检查 是否符合 正则表达式 。如果不符合 终止访问该url
		c.Visit(href)
	})
	c.OnHTML("body", func(e *colly.HTMLElement) {
		e.DOM.Each(func(i int, selection *goquery.Selection) {
			//匹配数据(页面dom结构)
			href := e.Request.AbsoluteURL(e.Attr("href"))

			//写入链接
			url := gositemap.NewUrl()
			url.SetLoc(href)
			url.SetLastmod(time.Now())
			url.SetChangefreq(gositemap.Daily)
			//获取页面权重
			url.SetPriority(getPriority(number))
			st.AppendUrl(url)

			number += 1
			fmt.Printf("计数:%d,链接:%s \n", number, href)
		})
	})
	c.OnError(func(response *colly.Response, err error) {
		//fmt.Println(err)
	})
	c.Visit(*targetUrl + "/")
	c.Wait()
	fmt.Printf("连接收集花费时间:%s,收集链接:%d个", time.Since(t), number)

	//bt,err := st.ToXml()
	//if err != nil{
	// fmt.Printf("异常:%v", err)
	// return
	//}
	//byte切片转string,好查看是否有错误
	//btString := string(bt)

	//输出
	//fmt.Println(btString)

	//生成文件导出
	filePath, err := st.Storage()
	if err != nil {
		fmt.Printf("%v", err)
		return
	}
	fmt.Println(filePath)
}

// 递减乱获取权重|很随意
func getPriority(num int) float64 {
	if num < 20 {
		return 1
	}
	newS := float64(num) / priority
	numQ := int(newS)

	//fmt.Printf("权重:%d \n",numQ)

	if num >= numQ {
		priority -= 0.01
	}

	return priority
}


我们随便找个网址来试试!

#启动命令,其他参数自己也可以尝试,然后完成会把所有的链接都存入一个sitemap.xml文件中
go run . -url=https://gs.dgg.cn

然后

这个也可以为SEO的同学,爬取整站链接,当做sitemap.xml文件

点赞1
点击评论0
收藏1
浏览 164
 

还没有评论,快来发表第一个评论吧

免责声明:凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证有关资料的准确性及可靠性,注册用户和一般页面游览者在使用前请进一步核实,并对任何自主决定的行为负责。本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任(包括侵权责任、合同责任和其它责任)
*尊重作者,转载请注明出处!

创作内容

开启你的爱凌峰创作之旅

发布首篇内容,开通创作中心
快来成为爱凌峰创作者吧~

写文章

板块热门【Golang】