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文件
还没有评论,快来发表第一个评论吧