Go语言并发爬虫的具体实现

目录
  • 写在前面
  • 1. 单线程爬虫
  • 2. 多线程爬虫
    • 2.1 channel main函数
    • 2.2 sync.WaitGroup
  • 3. 源码地址

写在前面

这篇文章主要让大家明白多线程爬虫,因为go语言实现并发是很容易的。

这次的服务端,是我们之前搭建的电子商城平台,所以我们不担心ip被封之类的问题。
而实际生产环境中,其实我们都是用python爬虫的。python实现多线程也很简单。

这次我们可以试试新玩法,试试go语言的并发爬虫。

主要是爬取第一页的商品,爬取十次,比较单线程和多线程的时间。

1. 单线程爬虫

 定义一个用户

var Client http.Client

主函数

func main() {
	url := "http://localhost:3000/api/v1/products"
	start := time.Now()
	for i := 0; i < 10; i++ {
		Spider(url, i)
	}
	elapsed := time.Since(start)
	fmt.Printf("Time %s", elapsed)
}

爬取函数

func Spider(url string, i int) {
	reqSpider, err := http.NewRequest("GET", url, nil)
	if err != nil {
		log.Fatal(err)
	}
	reqSpider.Header.Set("content-length", "0")
	reqSpider.Header.Set("accept", "*/*")
	reqSpider.Header.Set("x-requested-with", "XMLHttpRequest")
	respSpider, err := Client.Do(reqSpider)
	if err != nil {
		log.Fatal(err)
	}
	bodyText, _ := ioutil.ReadAll(respSpider.Body)
	var result Result
	_ = json.Unmarshal(bodyText, &result)
	fmt.Println(i,result.Data)
}

运行时间为:651.8207ms

2. 多线程爬虫

2.1 channel main函数

我们构造一个无缓冲的通道,来阻塞主进程,等待子进程的执行。

func main() {
	url := "http://localhost:3000/api/v1/products"
	ch := make(chan bool)
	start := time.Now()
	for i := 0; i < 10; i++ {
		go Spider(url, ch, i)
	}
	for i := 0; i < 10; i++ {
		<-ch
	}
	elapsed := time.Since(start)
	fmt.Printf("Time %s", elapsed)
}

最后记得在爬虫的结束的时候,把值写入到通道中,不然会一直阻塞主进程

运行时间:187.7921ms 比之前快了非常多。

2.2 sync.WaitGroup

定义一个进程组并加10个进程

	var wg sync.WaitGroup
	wg.Add(10)

开辟十个goruntime

	for i := 0; i < 10; i++ {
		go func(i int) {
			defer wg.Done()
			SpiderWaitGroup(url,i)
		}(i)
	}

阻塞主进程

wg.Wait()

结果:64.5246ms

3. 源码地址

GitHub地址:https://github.com/CocaineCong/Go-Spider-Demo

	NormalStart(url) // 单线程爬虫
	ChannelStart(url) // Channel多线程爬虫
	WaitGroupStart(url) // Wait 多线程爬虫

其实多线程的两种都差不多的,只是有时候会因为机器的原因而导致一些误差。

到此这篇关于Go语言并发爬虫的具体实现的文章就介绍到这了,更多相关Go语言并发爬虫 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Go语言实现的web爬虫实例

    本文实例讲述了Go语言实现的web爬虫方法.分享给大家供大家参考.具体分析如下: 这里使用 Go 的并发特性来并行执行 web 爬虫. 修改 Crawl 函数来并行的抓取 URLs,并且保证不重复. 复制代码 代码如下: package main import (     "fmt" ) type Fetcher interface {         // Fetch 返回 URL 的 body 内容,并且将在这个页面上找到的 URL 放到一个 slice 中.     Fetch(

  • Go语言并发爬虫的具体实现

    目录 写在前面 1. 单线程爬虫 2. 多线程爬虫 2.1 channel main函数 2.2 sync.WaitGroup 3. 源码地址 写在前面 这篇文章主要让大家明白多线程爬虫,因为go语言实现并发是很容易的. 这次的服务端,是我们之前搭建的电子商城平台,所以我们不担心ip被封之类的问题. 而实际生产环境中,其实我们都是用python爬虫的.python实现多线程也很简单. 这次我们可以试试新玩法,试试go语言的并发爬虫. 主要是爬取第一页的商品,爬取十次,比较单线程和多线程的时间.

  • 如何优雅地使用c语言编写爬虫

    大家在平时或多或少地都会有编写网络爬虫的需求.一般来说,编写爬虫的首选自然非python莫属,除此之外,java等语言也是不错的选择.选择上述语言的原因不仅仅在于它们均有非常不错的网络请求库和字符串处理库,还在于基于上述语言的爬虫框架非常之多和完善.良好的爬虫框架可以确保爬虫程序的稳定性,以及编写程序的便捷性.所以,这个cspider爬虫库的使命在于,我们能够使用c语言,依然能够优雅地编写爬虫程序. 1.爬虫的特性 配置方便.使用一句设置函数,即可定义user agent,cookie,time

  • Go语言并发编程之互斥锁Mutex和读写锁RWMutex

    目录 一.互斥锁Mutex 1.Mutex介绍 2.Mutex使用实例 二.读写锁RWMutex 1.RWMutex介绍 2.RWMutex使用实例 在并发编程中,多个Goroutine访问同一块内存资源时可能会出现竞态条件,我们需要在临界区中使用适当的同步操作来以避免竞态条件.Go 语言中提供了很多同步工具,本文将介绍互斥锁Mutex和读写锁RWMutex的使用方法. 一.互斥锁Mutex 1.Mutex介绍 Go 语言的同步工具主要由 sync 包提供,互斥锁 (Mutex) 与读写锁 (R

  • Go语言并发编程 sync.Once

    sync.Once用于保证某个动作只被执行一次,可用于单例模式中,比如初始化配置.我们知道init()函数也只会执行一次,不过它是在main()函数之前执行,如果想要在代码执行过程中只运行某个动作一次,可以使用sync.Once,下面来介绍一下它的使用方法. 先来看下面的代码: package main import ( "fmt" "sync" ) func main() { var num = 6 var once sync.Once add_one := fu

  • Go语言并发编程 互斥锁详情

    目录 1.互斥锁Mutex 1.1 Mutex介绍 1.2 Mutex使用实例 2.读写锁RWMutex 2.1 RWMutex介绍 2.2 RWMutex使用实例 1.互斥锁Mutex 1.1 Mutex介绍 Go 语言的同步工具主要由 sync 包提供,互斥锁 (Mutex) 与读写锁 (RWMutex) 就是sync 包中的方法. 互斥锁可以用来保护一个临界区,保证同一时刻只有一个 goroutine 处于该临界区内.主要包括锁定(Lock方法)和解锁(Unlock方法)两个操作,首先对进

  • Go语言做爬虫状态码返回418的问题解决

    目录 背景 原因分析 代码部分 背景  在使用Go语言做爬虫时,使用http.Get(url)去获取网页内容,状态码返回404,Body体为空. 原因分析  http.Get(url)是不需要设置header属性的http请求,比较简单快捷,但状态码返回418,表明我们需要设置其header属性,那么我们可以使用http.NewRequest,在设置其header属性即可~ 代码部分 func main7() { client := &http.Client{} url := "http

  • Go语言并发编程基础上下文概念详解

    目录 前言 1 Go 中的 Context 2 Context 接口 3 Context Tree 4 创建上下文 4.1 上下文创建函数 4.2 Context 使用规范 4.3 Context 使用场景 5 总结 前言 相信大家以前在做阅读理解的时候,一定有从老师那里学一个技巧或者从参考答案看个:结合上下文.根据上下文我们能够找到有助于解题的相关信息,也能更加了解段落的思想. 在开发过程中,也有这个上下文(Context)的概念,而且上下文也必不可少,缺少上下文,就不能获取完整的程序信息.那

  • 一文掌握Go语言并发编程必备的Mutex互斥锁

    目录 1. Mutex 互斥锁的基本概念 2. Mutex 互斥锁的基本用法 3. Mutex 互斥锁的底层实现 3.1 等待队列 3.2 锁状态 4. Mutex 互斥锁的注意事项 4.1 不要将 Mutex 作为函数或方法的参数传递 4.2 不要在获取 Mutex 的锁时阻塞太久 4.3 不要重复释放 Mutex 的锁 4.4 不要在锁内部执行阻塞或耗时操作 5. 总结 在并发编程中,我们需要处理多个线程同时对共享资源的访问问题.如果不加控制地同时访问共享资源,就会导致竞争条件(Race C

  • Go语言并发技术详解

    有人把Go比作21世纪的C语言,第一是因为Go语言设计简单,第二,21世纪最重要的就是并行程序设计,而Go从语言层面就支持了并行. goroutine goroutine是Go并行设计的核心.goroutine说到底其实就是线程,但是它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goroutine之间的内存共享.执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩.也正因为如此,可同时运行成千上万个并发任务.goro

  • Go语言并发模型的2种编程方案

    概述 我一直在找一种好的方法来解释 go 语言的并发模型: 不要通过共享内存来通信,相反,应该通过通信来共享内存 但是没有发现一个好的解释来满足我下面的需求: 1.通过一个例子来说明最初的问题 2.提供一个共享内存的解决方案 3.提供一个通过通信的解决方案 这篇文章我就从这三个方面来做出解释. 读过这篇文章后你应该会了解通过通信来共享内存的模型,以及它和通过共享内存来通信的区别,你还将看到如何分别通过这两种模型来解决访问和修改共享资源的问题. 前提 设想一下我们要访问一个银行账号: 复制代码 代

随机推荐