在python中经常会使用异步,线程池,进程池,解决io操作,在爬虫中并不建议使用进程池(消耗过大)
目标:会使用线程池
1:导入
import time
def demo1():
for i in range(3):
print(f"我饿了{i}")
time.sleep(1)
def demo2():
for i in range(3):
print(f"开饭了{i}")
time.sleep(1)
if __name__ == "__main__":
start=time.time()
demo1()
demo2()
end=time.time()
print(end-start)
#结果为
我饿了0
我饿了1
我饿了2
开饭了0
开饭了1
开饭了2
6.034951686859131
我们可以看到了只有在demo1完全运行完毕才会运行demo2,这个时候是单任务
2:基本使用方法
#1:导入threading模块
import threading
#2:使用threading模块中的Thread创建一个对象
t1=threading.Thread(target=xx)#xx为函数的名字
#3:调用这个实例对象的start方法让这个线程开始运行
t1.start()
import time
import threading
def demo1():
for i in range(3):
print(f"我饿了{i}")
time.sleep(1)
def demo2():
for i in range(3):
print(f"开饭了{i}")
time.sleep(1)
if __name__ == "__main__":
start=time.time()
t1=threading.Thread(target=demo1)
t2 = threading.Thread(target=demo2)
t1.start()
t2.start()
demo2()
end=time.time()
print(end-start)
#结果为:
我饿了0
开饭了0开饭了0
开饭了1开饭了1
我饿了1
开饭了2
开饭了2我饿了2
3.0304412841796875
我们可以看到这时候2个线程的一起跑
3:线程池的基本使用步骤
#1:导入包
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
#ThreadPoolExecutor线程池ProcessPoolExecutor进程池
def asd(data):
print(data)
#2:在线程池中创建几个线程
pool=ThreadPoolExecutor(10)#创建10个线程
#3:在线程池中发任务
for i in range(100):
pool.submit(asd,i)
#4:等待线程池把任务都执行完毕
pool.shutdown()
print("完毕")
4:在实际爬虫中的简单应用
爬取网站的所以图片
from concurrent.futures import ThreadPoolExecutor
import requests
import os
def tupian(page):
data = {
'per_page': '12',
'page': page,
'seo_tags': 'true'
}..........
#这个函数是获取每张图片的id
def downlong(id):
#这个函数是下载图片
def run():
pool=ThreadPoolExecutor(13)
a = int(input("请输入爬取的页数(大与3):"))
for page in range(3, a + 1):
id_list = tupian(page)
for id in id_list:
pool.submit(downlong,id)
pool.shutdown()
print("完毕")
#主要看怎么使用,函数就不给大家了
爬取菜价
import csv
from concurrent.futures import ThreadPoolExecutor
import requests
with open('北京新发地菜价.csv',mode='w', encoding='utf-8',newline='.0') as f:
wirter = csv.writer(f)#创建一个写入的对象
wirter.writerow(['菜名', '最低价(元)', '最高价(元)', '平均价(元)', '产地','发布日期'])
def get_one_page(pageNo):
data={
"limit":20,
"current":pageNo
#...........
if __name__ == '__main__':
# get_one_page(1)
with ThreadPoolExecutor(100) as t:#创建10000个线程
for i in range(1,22):#所有页数
t.submit(get_one_page,pageNo=i)#接任务
t.shutdown()
print('over!')
刷播放
import ctypes
import execjs
import time
from urllib.parse import urlparse, parse_qs
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import binascii
import requests
import datetime
from concurrent.futures import ThreadPoolExecutor
asd = execjs.compile("""
function ab () {
var e= (new Date).getTime().toString(36)
var t= Math.random().toString(36).replace(/^0./, "");
return "" .concat(e, "_").concat(t) //concat:相当于连接
}
""")
def aes_encrypt(data):
def creat_qn(data_str):
def creat_ckey(vid, rnd, guid, appVer, padtform):
def playvinfo_seconed(vid, rnd, appVer, padtform, flowid, guid, ckey):
def play_first(video_url, vid, pid, guid, fn, vkey, padtform, rnd, appver):
def run(video_url):
if __name__ == "__main__":
pool=ThreadPoolExecutor(10)#在线程池中创建10个线程
video_url = "https://w.yangshipin.cn/video?type=0&vid=u000058lp0z&ptag=yangshipincp"
for i in range(1,10):
pool.submit(run,video_url)
print(f"增加{i}个播放量")
# 等待线程池把任务都执行完毕
pool.shutdown()
print("完毕")