您现在的位置是:首页 > 经验记录>日常笔记>使用Golang写一个站点的sitemap生成工具,可命令指定站点url,输出地址,并发数等 网站首页 日常笔记

使用Golang写一个站点的sitemap生成工具,可命令指定站点url,输出地址,并发数等

使用包:

"flag"
"github.com/PuerkitoBio/goquery"
"github.com/douyacun/gositemap"
"github.com/gocolly/colly"
"github.com/gocolly/colly/extensions"
"regexp"
"time"


思路:

一、基于gocolly/colly遍历全站,且通过正则限制仅遍历指定网站链接内路径。 通过PuerkitoBio/goquery匹配页面 href循环遍历

二、使用douyacun/gositemap进行sitemap xml生成


代码如下:

package main

import (
   "flag"
   "fmt"
   "github.com/PuerkitoBio/goquery"
   "github.com/douyacun/gositemap"
   "github.com/gocolly/colly"
   "github.com/gocolly/colly/extensions"
   "regexp"
   "time"
)

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
}


---------------------------------------------分割线----------------------------------------------


使用(这里示例我只指定了目标地址,其他参数可看代码自行提供):

go run . -url=https://www.uppdd.com


结果:

...
计数:75,链接:https://www.uppdd.com/info?id=79
计数:76,链接:https://www.uppdd.com/info?id=115
计数:77,链接:https://www.uppdd.com/info?id=117
计数:78,链接:https://www.uppdd.com/info?id=90
计数:79,链接:https://www.uppdd.com/info?id=103
计数:80,链接:https://www.uppdd.com/info?id=83
计数:81,链接:https://www.uppdd.com/info?id=112
计数:82,链接:https://www.uppdd.com/module?module_id=6&page=1
计数:83,链接:https://www.uppdd.com/info?id=92
连接收集花费时间:9.0064424s,收集链接:83个sitemap.xml


文章评论

未开放
Top