传送门:exe文件
传送门:源码

生产者消费者模式

简介

比如两个进程A,B,它们共享一定大小的缓冲区,A生产数据放入缓冲区,B从缓冲区中提取数据并进行计算。在这里进程A充当生产者,进程B充当消费者。这就好比是一个水桶,如果生产者能力强,一直往桶里面加水,而消费者比较弱,如果水桶的水满了,最终还是得消费者消耗了一定分量的水后,生产者才能继续往里面加水,反过来道理也是一样,而生产者等待消费者消耗水的这个状态又称为阻塞。其中,消费者一般不止是一个,而是多个,消费者的个数又称为队列

为什么要用这个模式?

生产者消费者模式平衡了两者之间的能力,能够使python脚本运行更加高效、稳定

实例:用多线程与Queue实现生产者消费者模式

Queue模块详解:https://hovertree.com/h/bjaf/l55mdv6b.htm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import random,time,queue
from threading import Thread

def producer(name, count, q): #生产者生产包子
for i in range(count):
food = f'{name}{i}个包子'
print(food)
q.put(food) #生产者将包子放进缓冲区内

def consumer(name, q):
while True:
time.sleep(random.randint(1,3)) #模拟进程阻塞的样子
if q.empty():
break
print(f'{name} 消费了 {q.get()}') #消费者吃包子

if __name__ == '__main__':
q = queue.Queue()
print(q.empty())
for i in range(1, 4):
p = Thread(target=producer, args=(f'生产者{i}', 10, q))
p.start()

for i in range(1, 6):
c = Thread(target=consumer, args=(f'消费者{i}', q))
c.start()

实战:用生产者消费者模式爬取斗图吧表情包

斗图吧地址:https://www.doutula.com/
环境需求:python版本python3.6以上
需要用到的库:requests,requests_html,queue,threading,os,time(请自行下载)
requests-html官方文档:https://cncert.github.io/requests-html-doc-cn/#/

  1. 我们发现表情包图片被藏在class为page-content的div里面的a标签链接之中,注意,图片是藏在a标签链接当中,别把a标签链接当作图片链接
  2. 根据实际情况,写好脚本
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    import requests,requests_html,queue,threading,os,time
    '''初始化两个生产者,一个用来储存页数,一个用来储存图片链接'''
    total_page = queue.Queue()
    links = queue.Queue()

    '''预备各个要用到的参数'''
    r = requests_html.HTMLSession()
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0'} #下载图片时用到
    page_start = input('[*]你想从第几页开始爬取:') #开始爬取的页数
    page_end = input('[*]你想爬到多少页结束:') #结束爬取的页数
    path = input('[*]请输入你要下载的路径(可不填,默认在桌面下的Panda文件夹):').replace('\\','//')

    '''指定下载目录为Panda文件夹'''
    try:
    os.chdir(path)
    download_path = os.path.join(path,'Panda\\')
    except:
    os.chdir('C:\\Users\\{}\\desktop'.format(os.getlogin()))
    download_path = os.path.join(os.getcwd(),'Panda\\\\')
    if not os.path.exists(download_path):
    os.mkdir(download_path)
    print('\n[+]当前下载目录为{}'.format(download_path))

    '''指定下载页数,放进容器'''
    for i in range(int(page_start),int(page_end)+1):
    url = f'https://www.doutula.com/photo/list/?page={i}'
    total_page.put(url)

    start = time.time() #下载倒计时开始

    '''寻找图片的下载链接'''
    def find_links(total_page):
    while True:
    if total_page.empty():
    break
    u = total_page.get()
    h = r.get(u)
    div = h.html.find('.page-content',first=True)
    print(div)
    img = div.find('a')
    for i in range(len(img)):
    a = img[i].find('img')
    link = a[-1].html.split('data-backup=')[-1].strip('" / >')
    print('[+]已找到链接[{}]\n'.format(link))
    links.put(link)


    '''下载图片'''
    def download(download_path,links):
    while True:
    if total_page.empty() and links.empty():
    break
    filename = str(links.get()).split('/')[-1]
    data = requests.get(links.get(),headers=headers).content
    print('[+]正在下载\n' + filename)
    with open(download_path + str(filename),'wb') as f:
    f.write(data)
    f.close()

    for x in range(5):
    t1 = threading.Thread(target=find_links,args=(total_page,))
    t2 = threading.Thread(target=download,args=(download_path,links))
    t1.start()
    t2.start()
    t1.join() #阻塞线程,让其等所有线程执行完毕再结束程序,下面同理
    t2.join()
    end = time.time() - start
    print('[+]程序执行完毕,用时{}秒,已下载{}个文件'.format(round(end),len(os.listdir(download_path))))
    print('''
    ****************************
    * 程序执行完毕! *
    * *
    * Created by Jason *
    * https://freeaas.com *
    ****************************
    ''')

exe文件

环境需求:操作系统windows10(测试了在windows7运行不了),python版本3.6以上
需要用到的库:requests,requests_html,queue,threading,os,time(请自行下载)
若报错,请pip安装对应需要的库

exe文件:下载链接 密码:77re

木大木大

顺带记录一下:pyinstaller报错如下图

解决方案:使用以下命令打包

1
pyinstaller --onefile catchPanda.py --copy-metadata pyppeteer