package main

import (
"fmt"
"github.com/antchfx/htmlquery"
"golang.org/x/net/html"
"io/ioutil"
"net/http"
"strconv"
"strings"
"sync"
"time"
) var (
url = "https://www.woyaogexing.com/shouji/"
referUrl = "https://www.woyaogexing.com/shouji/"
referImg = "img2.woyaogexing.com"
) func downloadUrl(url string, refer string) []byte { client := &http.Client{}
req, e := http.NewRequest("GET", url, nil)
handError(e) req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36")
req.Header.Add("Referer", refer)
response, err := client.Do(req)
handError(err) defer response.Body.Close() byteContent, e := ioutil.ReadAll(response.Body)
handError(e)
return byteContent
} func parseContent(content []byte) []string {
reader := strings.NewReader(string(content))
html_node, i := html.Parse(reader)
handError(i) nodes, e := htmlquery.QueryAll(html_node, "//img/@src") handError(e)
var urls []string
for _, n := range nodes {
src := htmlquery.SelectAttr(n, "src")
urls = append(urls, src)
}
return urls
} func downloadImgs(url string, refer string,wg *sync.WaitGroup) {
prefix := strings.HasPrefix(url, "//img2")
if prefix != true {
return
}
defer wg.Done()
url = url[2:]
url = "http://"+url
fmt.Println("下载图片", url)
content := downloadUrl(url, referUrl)
str1 := strings.Split(url, "/")
file_name := str1[len(str1)-1]
file := ioutil.WriteFile("./imgs/"+file_name, content, 0777)
if file != nil {
fmt.Printf("下载图片%s 成功", file_name)
}
} func handError(err error) {
if err != nil {
fmt.Println(err)
}
} func main() { var wg sync.WaitGroup var totalPage = 10
for j:=0;j<=totalPage;j++{
wg.Add(1)
pageUrl := url+"index_"+strconv.Itoa(j) +".html"
go crawl(pageUrl)
wg.Done()
}
wg.Wait() time.Sleep(time.Second * 100)
} func crawl(url string ) {
var wg sync.WaitGroup byteContent := downloadUrl(url,referUrl)
urls := parseContent(byteContent)
fmt.Println(urls)
if len(urls) > 0 {
wg.Add(len(urls))
for _, v := range urls {
go downloadImgs(v, referImg,&wg)
}
wg.Wait()
}
}

  

go 多协程爬取图片的更多相关文章

  1. python协程爬取某网站的老赖数据

    import re import json import aiohttp import asyncio import time import pymysql from asyncio.locks im ...

  2. Python协程爬取妹子图(内有福利,你懂得~)

    项目说明: 1.项目介绍   本项目使用Python提供的协程+scrapy中的选择器的使用(相当好用)实现爬取妹子图的(福利图)图片,这个学会了,某榴什么的.pow(2, 10)是吧! 2.用到的知 ...

  3. 利用协程爬网页,自动切换io 精典案例:

    首先Python提供的协程库gevent好像并不能知道那些程序使用了io  所以要加一个补丁,mondey,以下同步和异步各爬一次的案例 : , from urllib import requesti ...

  4. python采用 多进程/多线程/协程 写爬虫以及性能对比,牛逼的分分钟就将一个网站爬下来!

    首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务.一个CPU,在一个时间切片里只能运行一个程序. 从操作系统的角度: 进程和线程,都 ...

  5. 线程池、进程池(concurrent.futures模块)和协程

    一.线程池 1.concurrent.futures模块 介绍 concurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor:线程池,提供异步调用 Pro ...

  6. Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就绪,挂起,运行) ,***协程概念,yield模拟并发(有缺陷),Greenlet模块(手动切换),Gevent(协程并发)

    Python进阶----异步同步,阻塞非阻塞,线程池(进程池)的异步+回调机制实行并发, 线程队列(Queue, LifoQueue,PriorityQueue), 事件Event,线程的三个状态(就 ...

  7. 多线程 多进程 协程 Queue(爬虫代码)

    快速理解多进程与多线程以及协程的使用场合和特点 首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务.一个CPU,在一个时间切片里只能运 ...

  8. Python3学习之路~10.2 协程、Greenlet、Gevent

    一 协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切 ...

  9. day35:线程队列&进程池和线程池&回调函数&协程

    目录 1.线程队列 2.进程池和线程池 3.回调函数 4.协程:线程的具体实现 5.利用协程爬取数据 线程队列 1.线程队列的基本方法 put 存 get 取 put_nowait 存,超出了队列长度 ...

随机推荐

  1. Android组件化 + MVP + MVVM

    前言 组件化和插件化已经提出了很久了,到现在也是比较稳定的一种架构方案了,在三年前,组件化和插件提出来没多久,前公司就已经在项目中使用了,只是当时还只是菜鸟,没有资格参与到架构的建设中,只是在大佬搭好 ...

  2. 【NOIP2013模拟】太鼓达人

    题目描述 七夕祭上,Vani牵着cl的手,在明亮的灯光和欢乐的气氛中愉快地穿行.这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员XLk.Poet_shy和lydrainbo ...

  3. HTML -- 表单元素2

    (1)<select>元素(下拉列表) <html> <body> <!-- 表单处理程序在action属性中指定 --> <form actio ...

  4. unserialize3 攻防世界

    序列化是将对象转换为便于保存的字符串, 而反序列化是将便于保存的字符串转换为字符串. _wakeup()魔法方法 如果直接传参给code会被__wakeup()函数再次序列化,所以要绕过他, 利用__ ...

  5. [Java核心技术]第九章-集合(Java集合框架、具体的集合、映射)

    9.1Java集合框架 一些有的没的 可以使用接口类型存放集合的引用.一旦改变了想法,只需要在调用构造函数的地方做一处修改. add方法用于向集合添加元素,如果添加元素确实改变了集合就返回true. ...

  6. Centos6.5 离线 Openssh 升级

    目录 OpenSSH 升级 一.基于 Dropbear 设置备用 ssh 服务器 二. Openssh 更新 2.1 ssh配置 备份 2.2 openssh 升级 Openssl 升级(由于Open ...

  7. 腾讯会议大规模使用Kubernetes的技术实践

    腾讯会议,一款提供灵活协作的线上会议解决方案.其中大量的模块是有状态服务,在使用Kubernetes为其进行容器化部署时,Pod升级需保持共享内存.长连接服务.升级时只容忍ms级抖动,需提供大规模分批 ...

  8. JVM-STW-stop the world

    Stop The World Stop一the一World,简称STW,指的是Gc事件发生过程中,会产生应用程序的停顿.停顿产生时整个应用程序线程都会被暂停,没有任何响应,有点像卡死的感觉,这个停顿称 ...

  9. Linux实战(8):查看文件大小

    du -sh *

  10. jenkins结合cygwin软件实现从centos发布代码rsync到windows server2019的过程

    jenkins结合cygwin软件实现从centos发布代码rsync到windows server2019的过程 1.下载cygwin这个软件打开https://cygwin.com/install ...