Go语言编写一个简单的并发小爬虫,爬取百度贴吧内容。这个小爬虫程序会在当前位置创建一个目录用于存储爬取的内容。Go语言天然的具有并发能力,这是语言特性,使用channel进行进程同步。通过Get方式访问网页,通过返回的*Response类型的变量获取其Body中的服务器端返回的数据。
具体源码如下(主要使用到的package包括:net/http,os):
package main
import (
"fmt"
"net/http"
"os"
"strconv"
)
func main() {
var strat, end int
var url_in string
fmt.Println("请输入贴吧url头")
fmt.Scan(&url_in)
fmt.Println("请输入起始页(>= 1)")
fmt.Scan(&strat)
fmt.Println("请输入终止页(>= 起始页)")
fmt.Scan(&end)
DoWork(url_in, strat, end)
}
func SpiderPage(url string, i int, page chan<- int) {
fmt.Printf("正在爬取第%d 页,url= %s\n", i, url)
result := *new(string)
resp, err := http.Get(url)
if err != nil {
fmt.Println("http.Get err= ", err)
return
}
defer resp.Body.Close()
// 开始读取网页body内容
buf := make([]byte, 4*1024)
for {
n, err := resp.Body.Read(buf)
if n == 0 { // 读取结束或者出问题
fmt.Println("resp.Body.Read err=", err)
break
}
result += string(buf[:n])
}
//拼接文件名
fileName := strconv.Itoa(i) + ".html"
// 把内容写入到文件
file, err2 := os.Create(fileName)
if err2 != nil {
fmt.Println("os.Create() err2= ", err2)
}
// 写入数据
file.WriteString(result)
// 关闭文件
file.Close()
page <- i
return
}
func DoWork(url_in string, strat, end int) {
// 创建一个通道用于同步
page := make(chan int)
fmt.Printf("正在爬取第%d页至第%d页。。。\n", strat, end)
// 明确爬取目标
// https://tieba.baidu.com/f?kw=%E7%BB%9D%E5%9C%B0%E6%B1%82%E7%94%9F&ie=utf-8&pn=
// 创建结果文件夹
err1 := os.Mkdir("Result", os.ModeDir)
if err1 != nil {
fmt.Println("os.Mkdir err= ", err1)
}
// 修改工作目录
e := os.Chdir("Result")
if err1 != nil {
fmt.Println("os.Chdir err= ", e)
}
for i := strat; i <= end; i++ {
url := url_in + strconv.Itoa((i-1)*50)
go SpiderPage(url, i, page)
}
for i := strat; i <= end; i++ {
fmt.Printf("第%d页爬取完成!\n", <-page)
}
}