发布于 

go实现小爬虫

Go 爬虫笔记 | 笔记整理!

Go 爬虫笔记

基础入门 | 简单易上手

网页访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func testHttpNewRequst(url string) {
// 1.建立客户端
client := http.Client{}

// 2.建立请求
// method, url string, body io.Reader
req, err := http.NewRequest("GET", url, nil)
req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36")

CheckErr(err)

// 3.客户端发送请求
response, err := client.Do(req)
CheckErr(err)
defer response.Body.Close()

// 4.提取数据
if response.StatusCode != 200 {
fmt.Println("网络访问失败!状态码:", response.StatusCode)
}
}

使用goquery对于网页进行解析 | 其中总是会用到findeach方法| 此处是解析 百度热榜

1
2
3
4
5
6
7
8
9
dom, err := goquery.NewDocumentFromReader(response.Body)
CheckErr(err)

// Find gets the descendants of each element in the current set of matched
// elements, filtered by a selector. It returns a new Selection object
// containing these matched elements.
dom.Find(".title-content-title").Each(func(i int, selection *goquery.Selection) {
fmt.Println("info:", selection.Text())
})

为了便于每次处理err,可以直接新建一下CheckErr函数避免重复操作

1
2
3
4
5
6
7
8
9
10
func CheckErr(err error) {
defer func() {
if ins, ok := recover().(error); ok {
fmt.Println("程序异常!", ins.Error())
}
}()
if err != nil {
panic(err)
}
}

小练手 | 我要个性网壁纸爬取

处理网页和原始数据

也可以只使用一个函数 看个人代码习惯

处理网页 | 使用goquery便于处理

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
// getPageUrl 解析网页 返回 *goquery.Document 数据类型 会进行close数据的
// 便于网页进行解析
func getPageUrl(url string) *goquery.Document {
// 1.建立客户端
client := http.Client{}

// 2.建立请求
// method, url string, body io.Reader
req, err := http.NewRequest("GET", url, nil)
req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36")

CheckErr(err)

// 3.客户端发送请求
response, err := client.Do(req)
CheckErr(err)
defer response.Body.Close()

// 4.提取数据
if response.StatusCode != 200 {
fmt.Println("网络访问失败!状态码:", response.StatusCode)
}
doc, err := goquery.NewDocumentFromReader(response.Body)
CheckErr(err)
return doc
}

处理原始网页 | 直接图片信息下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func getUrlContent(url string) io.ReadCloser {
// 1.建立客户端
client := http.Client{}

// 2.建立请求
// method, url string, body io.Reader
req, err := http.NewRequest("GET", url, nil)
req.Header.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36")

CheckErr(err)

// 3.客户端发送请求
response, err := client.Do(req)
CheckErr(err)
return response.Body
}

处理第一页请求 | 解析首页 试图找到 目标详情页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// testHttpNewRequst 进行网页解析 获取目标详情页数据信息
func testHttpNewRequst(url string, page int) {
doc := getPageUrl(url)

// Find gets the descendants of each element in the current set of matched
// elements, filtered by a selector. It returns a new Selection object
// containing these matched elements.

// 选择器或选择 因为都是txList标签开始 可以不用 | 操作
//pMain := doc.Find("div.pMain").Find("div.txList,div.txList.listRight").Size()
pMain := doc.Find("div.pMain div.txList")
sz := pMain.Size()
pMain.Each(func(i int, selection *goquery.Selection) {
// https://www.woyaogexing.com/touxiang/qinglv/2023/1280322.html
href, _ := selection.Find("a").Attr("href")
href = "https://www.woyaogexing.com" + href
title, _ := selection.Find("a").Attr("title")
fmt.Println(href, title)
// 处理目标详情页面
getPicLink(href, page)
})
fmt.Println(sz)
}

处理目标详情页面

注意出入title信息时候,注意不同版本电脑对于文件(夹)建立中字符串的限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// getPicLink 获取目标详情页数据信息
func getPicLink(url string, page int) {
doc := getPageUrl(url)
artCont := doc.Find(".contLeftA")
title := artCont.Find("h1").Text()
title = regexp.MustCompile(`[\/: *?"<>|]`).ReplaceAllString(title, "_")
filePath := fmt.Sprintf("page%d/%s", page, title)

err := os.MkdirAll(filePath, os.ModePerm)
CheckErr(err)

artCont.Find("ul.artCont.cl li.tx-img").Each(func(i int, selection *goquery.Selection) {
href, _ := selection.Find("a").Attr("href")
href = "https:" + href
picFile := fmt.Sprintf("%s/%d.jpeg", filePath, i+1)
fmt.Println(picFile)
writerToFile(picFile, href)
})
fmt.Println(title)
}

写入文件

1
2
3
4
5
6
7
8
9
10
11
12
13
// writerToFile开始进行写入文件
func writerToFile(path, url string) {
file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, os.ModePerm)
CheckErr(err)
content := getUrlContent(url)
defer content.Close()

reader := bufio.NewReaderSize(content, 32*1024)
writer := bufio.NewWriter(file)
n, err := io.Copy(writer, reader)
CheckErr(err)
fmt.Printf("文件:%5s 写入数据: %d 写入完成!\n", path, n)
}

进行简单爬取 | 直接goroutine 避免花里胡哨

1
2
3
4
5
6
7
8
9
10
11
12
13
func test() {
url := "https://www.woyaogexing.com/touxiang/qinglv/"
for i := 1; i <= 5; i++ {
cur := url
if i > 1 {
temp := url
cur = fmt.Sprintf("%sindex_%d.html", temp, i)
time.Sleep(time.Second * 1 / 2)
}
//fmt.Println(cur)
go testHttpNewRequst(cur, i)
}
}

主函数

可以处理goroutine信息 | 更简约 粗暴的是直接time.sleep就行

1
2
3
4
func main() {
test()
time.Sleep(50 * time.Second)
}

声明:爬虫资料仅供个人学习研究使用!尊重法律法规!侵权删!

代码过长不方便展示|已上传github