做爬虫不用说,就是用python就好,一个requests
包走天下。但是呢,听说golang中内置的http
包非常牛逼,咱就是说不得整点活,也刚好学习学习新东西,复习下http协议的请求和响应相关的知识点。话不多说,咱直接开整
本文章爬下必应壁纸先小试牛刀。狗头保命 狗头保命 狗头保命
爬虫流程概述
graph TD
请求数据 --> 解析数据 --> 数据入库
上图的流程图大家可以看到,其实爬虫并不麻烦,整个流程就只有三步而已。接下来具体聊聊每一步需要做什么
请求数据:在这里我们需要使用golang中的内置包http包向目标地址发起请求,这一步就完成了
解析数据:这里我们需要对请求到的数据进行解析,因为不是整个请求到的数据我们都需要,我们只需要某些具体的关键的数据而已。这一步也叫数据清洗
数据入库:不难理解,这就是将解析好的数据进行入库操作
实战分析
先到必应壁纸官网上观察,做爬虫的话是需要对数据特别敏感的。这是首页信息,整个页面是非常简洁的
接下来,需要调出浏览器的开发者工具(这个大家应该都非常熟悉吧,不熟悉的话很难跟下去的喔)。直接按下F12
或者右键点击检查但是呢?在必应壁纸上,右键不能调用控制台,只能手动调出了。大家不用担心,按照第一张图操作就好。如果有同学的chrome是中文的,也是一样的操作,选择更多工具,选择开发者工具即可
不出意外呢,大家肯定看到的是这样的页面
这个没关系的,只是必应壁纸网站的一些反爬错误而已。(我很久之前爬的时候还没有这个反爬错误)这个是不影响我们操作的
接下来选择这个工具,帮助我们快速定位到我们想要的元素上然后我们就能找到我们所需的图片信息
代码实战
下面是爬取一页的数据
package main
import (
"fmt"
"github.com/PuerkitoBio/goquery"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"time"
)
func Run(method, url string, body io.Reader, client *http.Client) {
req, err := http.NewRequest(method, url, body)
if err != nil {
log.Println("获取请求对象失败")
return
}
req.Header.Set("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")
resp, err := client.Do(req)
if err != nil {
log.Println("发起请求失败")
return
}
if resp.StatusCode != http.StatusOK {
log.Printf("请求失败,状态码:%d", resp.StatusCode)
return
}
defer resp.Body.Close() // 关闭响应对象中的body
query, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
log.Println("生成goQuery对象失败")
return
}
query.Find(".container .item").Each(func(i int, s *goquery.Selection) {
imgUrl, _ := s.Find("a.ctrl.download").Attr("href")
imgName := s.Find(".description>h3").Text()
fmt.Println(imgUrl)
fmt.Println(imgName)
DownloadImage(imgUrl, i, client)
time.Sleep(time.Second)
fmt.Println("-------------------------")
})
}
func DownloadImage(url string, index int, client *http.Client) {
req, err := http.NewRequest("POST", url, nil)
if err != nil {
log.Println("获取请求对象失败")
return
}
req.Header.Set("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")
resp, err := client.Do(req)
if err != nil {
log.Println("发起请求失败")
return
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Println("读取请求体失败")
return
}
baseDir := "./image/image-%d.jpg"
f, err := os.OpenFile(fmt.Sprintf(baseDir, index), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err != nil {
log.Println("打开文件失败", err.Error())
return
}
defer f.Close()
_, err = f.Write(data)
if err != nil {
log.Println("写入数据失败")
return
}
fmt.Println("下载图片成功")
}
func main() {
client := &http.Client{}
url := "https://bing.ioliu.cn/?p=%d"
method := "GET"
Run(method, url, nil, client)
}
下面是爬取多页数据爬取多页的代码没有多大的改动,我们还是需要先观察网站的特点
发现什么了吗?第一页p=1,第二页p=2,第十页p=10
所以我们直接起一个for循环,然后复用之前爬取单页的代码就行
// 爬取多页的main函数如下
func main() {
client := &http.Client{}
url := "https://bing.ioliu.cn/?p=%d"
method := "GET"
for i := 1; i < 5; i++ { // 实现分页操作
Run(method, fmt.Sprintf(url, i), nil, client)
}
}
总结
在我们这个例子中,我们解析网页数据使用的工具的一个第三方包,因为用正则真的太麻烦了
- 用css选择器:goQuery
- 用xpath选择器:htmlquery
- 正则:内置包,不推荐,正则规则不好写
以上就是详解怎么使用Golang爬取必应壁纸的详细内容,更多请关注编程网其它相关文章!