Golang网络爬虫框架gocolly/colly是比较有名的,考虑自做一个获取上市信息的软件,研究一下它。
依照着学习一下代码,主要是如何分离有效数据。
/*
功能:爬取相关上市公司信息
时间:2020.10.12
作者:Ease
网站:i.SCWY.net
说明:
记录:
*/
package main
import (
"log"
"math/rand"
"github.com/PuerkitoBio/goquery"
"github.com/gocolly/colly"
)
//产生随机字符串
func RandomString() string {
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
b := make([]byte, rand.Intn(10)+10)
for i := range b {
b[i] = letterBytes[rand.Intn(len(letterBytes))]
}
return string(b)
}
//主功能
func main() {
//创建 collector
c := colly.NewCollector()
c.AllowURLRevisit = false //不要重复
//请求执行之前调用
c.OnRequest(func(r *colly.Request) {
r.Headers.Set("User-Agent", RandomString()) //用于避免反爬
})
//错误回调
c.OnError(func(_ *colly.Response, err error) {
log.Println("发生错误: ", err)
})
//在收到响应标头后调用
c.OnResponseHeaders(func(r *colly.Response) {
log.Println("响应标头: ", *(r.Headers))
})
//完成抓取后执行
c.OnScraped(func(r *colly.Response) {
log.Println("完成: ", r.Request.URL)
})
//通过层级,定位需要的行内容
c.OnHTML("td>table.list-div-table>tbody>tr", func(e *colly.HTMLElement) {
//log.Println(e.Text)
log.Println(e.ChildText("td:first-child")) //第一个td的内容
log.Println(e.ChildText("td:nth-child(2)")) //第二个td的内容
log.Println(e.ChildText("td:nth-child(3)")) //第三个td的内容
log.Println(e.ChildText("td:nth-child(4)"))
log.Println(e.ChildText("td:nth-child(5)"))
//在当前内容节点树上查找内容
e.DOM.Parent().Parent().Next().Find("table.list-div-table>tbody>tr").Each(func(_ int, s *goquery.Selection) {
log.Println(s.Find("td:nth-child(1)").Text())
})
})
//如果接收到的内容是HTML,则在OnResponse之后立即调用
// c.OnHTML("a[href]", func(e *colly.HTMLElement) {
// //e.Request.Visit(e.Attr("href")) //再爬
// log.Printf("Link: %q -> %s\n", e.Text, e.Attr("href"))
// })
//如果接收的内容是HTML或XML,则在OnHTML之后立即调用
// c.OnXML("//h1", func(e *colly.XMLElement) {
// log.Println(e.Text)
// })
//响应返回之后调用
// c.OnResponse(func(r *colly.Response) {
// log.Println("Visited: ", r.Request.URL)
// })
//启动网页访问
c.Visit("http://www.csindex.com.cn/zh-CN/downloads/industry-price-earnings-ratio")
}
上手还是比较容易,真正的爬虫还需要IP池,数据存储等。