目的:
搜索CSDN博客,将搜索到博客,爬取博客名称、博客作者、博客链接、发布时间、阅读量。
输入搜索开始页码、结束页码,对每页搜索结果进行多协程爬取。
实现步骤:
1. 博客主页搜索“区块链”,点击第2页,跳转到第2页。得到搜索结果的第2页的网址
https://so.csdn.net/so/search/s.do?p=2&q=%E5%8C%BA%E5%9D%97%E9%93%BE&t=blog&domain=&o=&s=&u=&l=&f=&rbg=0
2.找到搜索结果页码规律,p=2,替换2,就可以跳转到相应搜索结果页面。
3. 查看搜索页码的源码,用正则表达式,提取博客url。
4. 根据url,爬取博客详情,将爬取的结果用正则表达式,提取博客名称、博客作者、博客链接、发布时间、阅读量。
5.将爬取的每页的结果保存到一个文件中。
根据以上步骤,可将本程序代码,应用到其他网页。只要找到源码的规律,替换相关的url和正则表达式,即可爬取相关页码内容。
注意:go语言在实现高并发爬取时,要用到channel类型,是go非常特别的一种类型,类似管道,可以实现线程同步、线程间通信。双通道chan类型管道中无数据时会阻塞线程,所以可以监控页面是否爬取完成,页面爬取完成后在chan中放入数据,在主线程中迭代chan,直到全部页码爬取完成,程序结束。
代码如下:代码要从下开始往上看,执行顺序也是这样,执行步骤如上所述,注释也很清楚
package main
import (
"fmt"
"io"
"net/http"
"os"
"regexp"
"strconv"
// "strings"
)
//爬取博主名author,博客名title,博客地址blogSite,发布日期publishTime,浏览量browingTimes
//封装一个函数,爬取一页内容
func SpiderOnePage(url string) (result string, err error) {
resp, err1 := http.Get(url)
if err1 != nil {
err = err1
fmt.Println("http.Get err1 = ", err1)
return
}
defer resp.Body.Close()
//读取网页的内容
buf := make([]byte, 4*1024)
for {
n, err2 := resp.Body.Read(buf)
if n == 0 {
//如果读取接收,直接break
if err2 == io.EOF {
break
//如果是其他错误,就打印出来
} else {
fmt.Println("resp.Body.Read err2 = ", err2)
break
}
}
result += string(buf[:n]) //读取多少,写多少
}
ret