Go语言编写并发小爬虫

           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)
	}

}

猜你喜欢

转载自blog.csdn.net/smallerxuan/article/details/83312108