golang 爬虫修炼03 ---百度贴吧并发爬虫

总目标

爬取百度贴吧指定词条搜索结果的多页,并保存指定页面

工作流程

1. 明确目标 Url

2. 发送请求,获取应答数据包。 http.Get(url)

3. 保存文件内容	

一、寻找url

在这里插入图片描述
来到贴吧首页,F12开启浏览器抓包,随便输入一个词条搜索
在这里插入图片描述

抓到搜索后的首页url
https://tieba.baidu.com/f/search/res?ie=utf-8&qw=%E7%8E%8B%E8%80%85
第二页url:
https://tieba.baidu.com/f/search/res?isnew=1&kw=&qw=%CD%F5%D5%DF&rn=10&un=&only_thread=0&sm=1&sd=&ed=&pn=2
第三页url:
https://tieba.baidu.com/f/search/res?isnew=1&kw=&qw=%CD%F5%D5%DF&rn=10&un=&only_thread=0&sm=1&sd=&ed=&pn=3

对比可以发现pn参数为几返回的页面就是第几页
qw参数是搜索的词条,被url强制编码的中文字符
rn是每页显示条数
删去无用参数,得到需要请求的url:
https://tieba.baidu.com/f/search/res?isnew=1&qw=%CD%F5%D5%DF&rn=10&pn=3

二、发送请求(http.Get)

使用http.Get 发起get请求
封装一个get函数,接收要搜索的关键词和页数
并返回爬取的网页body

func get(str string, page int) string {
	url := fmt.Sprintf("https://tieba.baidu.com/f/search/res?isnew=1&qw=%s&rn=10&pn=%d", url.QueryEscape(str), page)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}
	return string(body)
}

三、保存文件

封装一个函数,作为保存文件

func save_file(body string, i int) {
	file, err := os.Create("第" + strconv.Itoa(i) + "页.html")
	if err != nil {
		fmt.Println(err)
	}
	file.WriteString(body)
	file.Close()
}

四、主程序组装

获取用户输入,然后进行爬取和保存

func main() {
	var str string
	var num1 int
	var num2 int
	fmt.Println("输入要搜索的关键词")
	fmt.Scanln(&str)
	fmt.Println("请输入要爬取第几页到第几页 例:1 10")
	fmt.Scanln(&num1, &num2)
	fmt.Println(str, num1, num2)
	for i := 1; i <= num2; i++ {
		body := get(str, i)
		save_file(body, i)
	}
}

直接运行
在这里插入图片描述
成功!,由于这个io操作文件导致速度很慢
所以说加入协程

五、加入并发

定义一个 waitgroup、读写锁在这里插入图片描述

加入协程、waitgroup,给io操作加上读写锁

在这里插入图片描述

最终代码

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strconv"
	"sync"
)

func get(str string, page int) {
	defer wg.Done()
	url := fmt.Sprintf("https://tieba.baidu.com/f/search/res?isnew=1&qw=%s&rn=10&pn=%d", url.QueryEscape(str), page)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}
	lock.RLock()
	save_file(string(body), page)
	lock.RUnlock()
}

func save_file(body string, i int) {
	file, err := os.Create("./main/htmls/第" + strconv.Itoa(i) + "页.html")
	if err != nil {
		fmt.Println(err)
	}
	file.WriteString(body)
	file.Close()
	fmt.Println("第" + strconv.Itoa(i) + "页爬取成功")
}

var wg sync.WaitGroup
var lock sync.RWMutex

func main() {
	var str string
	var num1 int
	var num2 int
	fmt.Println("输入要搜索的关键词")
	fmt.Scanln(&str)
	fmt.Println("请输入要爬取第几页到第几页 例:1 10")
	fmt.Scanln(&num1, &num2)
	fmt.Println(str, num1, num2)
	for i := 1; i <= num2; i++ {
		wg.Add(1)
		go get(str, i)
	}
	wg.Wait()
}


在这里插入图片描述

运行后会发现速度特别快

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值