20408912 发表于 2017-4-3 18:02

python简单图片爬虫单线程与多线程开源讲解

本帖最后由 20408912 于 2017-4-3 18:04 编辑

最近学了几个星期的python 一直在学习基础的变量 列表 循环之类的
前几天看了一节课程 我也参照了一下 做出了python多线程图片爬虫
在这里和大家一起学习探讨一下 求大神指教


第一步我们先做一个单线程图片爬虫

import time    #添加模块

#这里建立了两个常量
CC_LIST = ('CN IN US ID BR PK NG BD RU JP'      #这是图片的参数
         'MX PH VN ET EG DE IR TR CD FR').split()
BASE_URL = 'http://flupy.org/data/flags'          #这是抓取图片的网站参数
DEST_DIR = 'downloads/'
#建立入口
def main():
    start = time.time() #爬虫开始时间
    get_many(CC_LIST)   #过程
    stop = time.time()#爬虫结束时间
    print(stop-start)   #结束时间减去开始时间 程序结束时会输出时间
#入口的函数调用
main()
我们这是建立了入口 和抓取的网址和参数
下一步
def get_one(cc):
    image = download_flag(cc)#下载图片 储存到内存
    show_flag(cc)
    save_flag(image,cc.lower()+'.gif') #保存到文件里

def get_many(cc_list):
    for cc in sorted(cc_list):
      #迭代 每次拿到图片
      get_one(cc)#抓一个图片
我们这是下载图片到内存 在保存到本地
下一步
def download_flag(cc):
    url = '{}/{cc}/{cc}.gif'.format(BASE_URL, cc=cc.lower())    #lower 转换成小写
    response = urlopen(url)   #响应 (Web)
    image = response.read()   # 图片是二进制
    return image

def save_flag(image,filename):
    path = os.path.join(DEST_DIR,filename)
    with open(filename,'wb') as f:   # w表示 write写wb 二进制写
      f.write(image)
这里是网址与参数结合 启动线程
然后再添加模块
#在顶部在添加模块
import os
from urllib.request import urlopen

还有两段最后的代码
def show_flag(cc):
    print(cc)   #启动爬虫   (单线程)

单线程完整代码:
import time
import os
from urllib.request import urlopen

CC_LIST = ('CN IN US ID BR PK NG BD RU JP'
         'MX PH VN ET EG DE IR TR CD FR').split()
BASE_URL = 'http://flupy.org/data/flags'
DEST_DIR = 'downloads/'

def download_flag(cc):
    url = '{}/{cc}/{cc}.gif'.format(BASE_URL, cc=cc.lower())
    response = urlopen(url)
    image = response.read()
    return image

def show_flag(cc):
    print(cc)

def save_flag(image,filename):
    path = os.path.join(DEST_DIR,filename)
    with open(filename,'wb') as f:
      f.write(image)



def get_one(cc):
    image = download_flag(cc)
    show_flag(cc)
    save_flag(image,cc.lower()+'.gif')



def get_many(cc_list):
    for cc in sorted(cc_list):
      get_one(cc)


def main():
    start = time.time()
    get_many(CC_LIST)
    stop = time.time()
    print(stop-start)


main()


我们来运行一下:
单线程耗时10多秒 抓取了所有图片(代码或许有bug 有时可能崩溃)

我们来试试多线程
只需要修改:
#多线程修改
#在顶部在添加参数
from concurrent import futures

#把 get_many 修改
def get_many(cc_list):
    with futures.ThreadPoolExecutor(20) as executor:   #20 是20线程
      res = executor.map(get_one,sorted(cc_list))



完整多线程代码:
import time
import os
from urllib.request import urlopen
from concurrent import futures

CC_LIST = ('CN IN US ID BR PK NG BD RU JP'
         'MX PH VN ET EG DE IR TR CD FR').split()
BASE_URL = 'http://flupy.org/data/flags'
DEST_DIR = 'downloads/'

def download_flag(cc):
    url = '{}/{cc}/{cc}.gif'.format(BASE_URL, cc=cc.lower())
    response = urlopen(url)
    image = response.read()
    return image

def show_flag(cc):
    print(cc)

def save_flag(image,filename):
    path = os.path.join(DEST_DIR,filename)
    with open(filename,'wb') as f:
      f.write(image)

def get_one(cc):
    image = download_flag(cc)
    show_flag(cc)
    save_flag(image,cc.lower()+'.gif')

def get_many(cc_list):
    with futures.ThreadPoolExecutor(20) as executor:
      res = executor.map(get_one,sorted(cc_list))


def main():
    start = time.time()
    get_many(CC_LIST)
    stop = time.time()
    print(stop-start)

main()


多线程测试:
只耗时1到2秒左右
这就是多线程与双线程的区别
当然 多线程更消耗内存资源 你如你内存允许 就算1000线程都可以。
求各位大佬指点

20408912 发表于 2017-4-3 18:12

JOB123 发表于 2017-4-3 18:10
图片的网站参数 403

你仔细看一下代码 看图片参数 CC_LIST 的参数   被转成小写网址+参数+'.gif' =http://flupy.org/data/flags/cn/cn.gif

small_four 发表于 2017-4-3 19:59

不错学习了                                 

JOB123 发表于 2017-4-3 18:10

本帖最后由 JOB123 于 2017-4-3 18:28 编辑

嗯,看看

LDarkMiku 发表于 2017-4-3 19:01

看下看下看下

gxu 发表于 2017-4-3 19:32

谢谢楼主分享

shadan 发表于 2017-4-3 20:09

同样在学习,看一下~

内心xi 发表于 2017-4-3 20:47

Are you QQ?

Huiever 发表于 2017-4-3 23:17

厉害了,学习了

谁折南枝傍小丛 发表于 2017-4-3 23:25

感谢分享,学习下
页: [1] 2
查看完整版本: python简单图片爬虫单线程与多线程开源讲解