Colly是Golang世界最知名的Web爬虫框架了,它的API清晰明了,高度可配置和可扩展,支持分布式抓取,还支持多种存储后端(如内存、Redis、MongoDB等)。这篇文章记录我学习使用它的的一些感受和理解。
首先安装它:
1 |
go get -u github.com/gocolly/colly/... |
这个go get
和之前安装包不太一样,最后有...
这样的省略号,它的意思是也获取这个包的子包和依赖。
我用它爬取学校官网的一部分新闻内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
package main import ( "fmt" "github.com/antchfx/htmlquery" "github.com/gocolly/colly" "log" "os" "strings" "sync" ) var wait sync.WaitGroup var news_arr=make([]interface{},0) func main() { c := colly.NewCollector( colly.Async(true), //允许并发执行 //colly.UserAgent("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"), //设置代理 ) c.Limit(&colly.LimitRule{DomainGlob: "*.douban.*", Parallelism: 5}) //parallelism后面跟的数字代表最大允许并发请求的数目。 //发起请求时调用 c.OnRequest(func(r *colly.Request) { log.Println("Visiting", r.URL) }) //发生错误时调用 c.OnError(func(_ *colly.Response, err error) { log.Println("Something went wrong:", err) }) //页面响应结果 c.OnResponse(func(r *colly.Response) { doc, err := htmlquery.Parse(strings.NewReader(string(r.Body))) //htmlquery.Parse需要接受一个实现io.Reader接口的对象,所以用了strings.NewReader(string(r.Body)) if err != nil { log.Fatal(err) } nodes := htmlquery.Find(doc, `//html/body/div[3]/div[3]/div[1]/div[1]/div[2]/ul/li/a`) //使用xpath语法匹配a标签 for _, node := range nodes { slice:=make(map[string]string) url_point := htmlquery.FindOne(node, "@href") //读取a标签中的href属性,返回的是一个指针类型 url:="http://www.wntc.edu.cn/"+(htmlquery.InnerText(url_point)) title:=htmlquery.InnerText(node) slice["url"]=url slice["title"]=title news_arr=append(news_arr, slice) } }) c.Visit("http://www.wntc.edu.cn/") //爬虫网址 c.Wait() //等待该页面爬取,获得页面上的url for key,v:=range news_arr { url:=v.(map[string]string)["url"] wait.Add(1) go content(url,key) } wait.Wait() is_finish:=write("F:/笔记/Go笔记/ceshi.txt") if is_finish { fmt.Println("写入成功") } } //爬取内容操作 func content(url string,key int){ defer wait.Done() doc,err:=htmlquery.LoadURL(url) if err != nil { fmt.Println("爬取错误") os.Exit(1) } nodes := htmlquery.Find(doc, `//*[@id="vsb_content_2"]/div`) //使用xpath语法匹配a标签 for _, node := range nodes { info:=htmlquery.InnerText(node) (news_arr)[key].(map[string]string)["info"]=info } } //写入文件操作 func write(src string) (is_finish bool){ is_finish=false fl, err := os.OpenFile(src, os.O_APPEND|os.O_CREATE, 0644) defer fl.Close() if err!=nil { fmt.Println("文件打开失败") os.Exit(1) } for _,v:=range news_arr{ message:=v.(map[string]string) str:=`标题:`+message["title"]+" " str+=`url:`+message["url"]+" " str+=`内容:`+message["info"]+" " var strBytes=[]byte(str) //将字符串强制类型转换为字节切片 n, err := fl.Write(strBytes) if err == nil && n < len(strBytes) { fmt.Println("文件写入失败") os.Exit(1) } } is_finish=true return } |
© 著作权归作者所有
文章评论(0)