Day7 线程池和指令系统
文章目录
1. 线程等待(阻塞)
# 引入模块
from threading import Thread
from time import sleep
from datetime import datetime
from random import randint
def download(name):
print(f'{name}开始下载:{datetime.now()}')
sleep(randint(2, 7))
print(f'{name}下载结束:{datetime.now()}')
if __name__ == '__main__':
t1 = Thread(target=download, args=('明日战纪',))
t2 = Thread(target=download, args=('斗罗大陆',))
t3 = Thread(target=download, args=('独行月球',))
# 示例1:三个电影都下载结束后打印“全部下载完成”
t1.start()
t2.start()
t3.start()
# 1. 子线程对象.join() - 阻塞当前线程直到指定子线程任务完成
t1.join()
t2.join()
t3.join()
print('-------------全部打印完成--------------')
# 示例2:前两个电影下载完成后才下载第三个电影
t1.start()
t2.start()
t1.join()
t2.join()
t3.start()
2. 线程池
'''
Author:KathAmy
Date:2022/8/19 10:13
键盘敲烂,共同进步!
'''
# 1.线程池 -
'''
线程池的工作原理:先创建指定个数的线程,然后添加多个任务(任务数量>线程数量),
让线程池中的线程去执行添加的所有任务,知道所有任务都执行完(线程池中的每个线程可能会执行多个任务)
'''
from threading import Thread, current_thread
from time import sleep
from datetime import datetime
from random import randint
from concurrent.futures import ThreadPoolExecutor
def download(name):
print(f'{name}开始下载:{datetime.now()}', current_thread())
sleep(randint(2, 7))
print(f'{name}下载结束:{datetime.now()}')
if __name__ == '__main__':
# 方案1:直接使用多线程下载1000个电影
num = 0
for _ in range(10):
ts = []
for x in range(100):
num += 1
t = Thread(target=download, args=(f'电影{num}',))
ts.append(t)
t.start()
for x in ts:
x.join()
# 方案2:使用线程池下载1000个电影
# 1.创建线程池
# ThreadPoolExecutor(线程数最大值)
pool = ThreadPoolExecutor(3)
# 2.添加任务
# 1)一次添加一个任务:submit(函数, 实参1, 实参2, 实参3, ...)
# 注意:实参的数量有前面的函数在调用的时候需要的实参来决定
pool.submit(download, '肖生克的救赎')
pool.submit(download, '霸王别姬')
# 2)同时添加多个任务:map(函数, 参数对应的序列)
# 注意:使用map添加多个任务的时候,任务对应的函数必须是有且只有一个参数的函数
pool.map(download, ['冰雪奇缘', '海蒂', '一起老去'])
# 3.关闭线程池
# 线程池关闭后无法再添加新的任务,并且会阻塞当前线程等待整个线程池的任务都完成
pool.shutdown()
print('完成啦!')
3. 线程爬某瓣电影
'''
Author:KathAmy
Date:2022/8/19 17:33
键盘敲烂,共同进步!
'''
import requests
from bs4 import BeautifulSoup
import csv
from concurrent.futures import ThreadPoolExecutor
def get_net_data(url: str):
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
}
proxies = {
'http': '121.206.253.171:4512',
'https': '121.206.253.171:4512'
}
response = requests.get(url, headers=headers, proxies=proxies)
# return response.text
analysis_data(response.text)
def analysis_data(html: str):
# 解析数据
soup = BeautifulSoup(html, 'lxml')
all_film_div = soup.select('.grid_view>li>.item')
all_data = [] # 保存每一页所有的电影
for div in all_film_div:
rank = div.select_one('.pic>em').text
name = div.select_one('.title').text
info = div.select_one('.bd>p').text.strip().split('\n')[-1].strip()
# time, country, category = info.split('/')
info_list = info.split('/')
time = info_list[0]
country = info_list[-2]
category = info_list[-1]
score = div.select_one('.rating_num').text
comment_count = div.select('.star>span')[-1].text[:-3]
intro_span = div.select_one('.inq')
if intro_span:
intro = intro_span.text
else:
intro = ''
all_data.append([int(rank), name, score, time.strip(), country.strip(), category.strip(), comment_count, intro])
films.append(all_data)
if __name__ == '__main__':
films = [] # 保存整个网站所有的电影
# [
# [[26, ], [], [], ...],
# [[1], [], [], ...],
# [[23], [], [], ...],
# ]
f = open('电影.csv', 'w', encoding='utf-8', newline='')
writer = csv.writer(f)
writer.writerow(['排名', '电影名称', '评分', '上映时间', '国家', '类型', '评论数', '简介'])
pool = ThreadPoolExecutor(10)
for page in range(0, 251, 25):
url = f'https://movie.douban.com/top250?start={page}&filter='
pool.submit(get_net_data, url)
pool.shutdown()
# 优化方案:按页排序
films.sort()
for x in films:
writer.writerows(x)
4. 某瓣电影多线程下载数据
'''
Author:KathAmy
Date:2022/8/19 17:37
键盘敲烂,共同进步!
'''
import requests
import csv
from bs4 import BeautifulSoup
from threading import Thread
from datetime import datetime
f = open('多线程豆瓣.csv', 'a', encoding='utf-8', newline='')
writer = csv.writer(f)
writer.writerow(['名字', '分数', '评论人数', '介绍'])
def get_html(url):
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
}
response = requests.get(url=url, headers=headers)
return response.text
def download(page, url: str):
print(f'第{page}页开始下载:{datetime.now()}')
html = get_html(url)
soup = BeautifulSoup(html, 'lxml')
all_li = soup.select('.grid_view>li')
new_list = []
for li in all_li:
name = li.select_one('.item>.info>.hd .title').text
scores = li.select_one('.bd>.star>.rating_num').text
numbers = li.select_one('.item>.info>.bd>.star>span:nth-child(4)').text
info = li.select_one('.bd>.quote')
if info:
info = li.select_one('.bd>.quote').text.strip()
else:
info=''
new_list.append([name, scores, numbers, info])
print(new_list)
writer.writerows(new_list)
print(f'第{page}页下载完成:{datetime.now()}')
if __name__ == '__main__':
ts = []
for i in range(0, 51, 25):
url = f'https://movie.douban.com/top250?start={i}&filter='
t = Thread(target=download, args=(i, url))
ts.append(t)
t.start()
# 等待所有的子线程任务都结束后再接着执行
for x in ts:
x.join()
f.close()
5. 常用指令操作
执行指令的工具: Windows - 命令提示符(cmd) 、Mac - 终端
5.1 运行python程序
运算程序的计算机必须先安装python环境
win: python py文件路径
mac: python3 py文件路径
5. 2 进入文件夹: cd
cd 文件夹相对路径、文件夹绝对路径
注意:如果是windows操作系统,cd操作如果要跨盘需要先切盘,然后再cd
切盘方法:C:、E:、D:
5.3 查看当前文件夹的内容
win: dir
Mac:ls
5.4 用指令创建虚拟环境
第一步:找到一个用来放虚拟环境的文件夹
第二步:通过cd指令进入到存放虚拟环境的文件夹中
第三步:创建虚拟环境
python -m venv 虚拟环境名
python3 -m venv 虚拟环境名
第四步:激活虚拟环境
(mac) source 虚拟环境目录/bin/activate
(windows) 虚拟环境目录\ Scripts\activate.bat
第五步:退出虚拟环境
deactivate
5.5 常用pip指令
(pip - Python包管理工具)
pip list - 查看当前环境已经安装过的所有的第三方库
pip install 第三方库名称 - 下载并且安装指定的第三方库
pip install 第三方库名称 -i 镜像地址 - 在指定的镜像地址中下载安装
pip install 第三方库名称==版本号 -i 镜像地址
pip install 第三方库名称1 第三方库名称2
pip freeze > 依赖文件名 - 生成依赖文件
pip install -r 依赖文件路径 - 批量安装
pip uninstall 第三方库名称 - 卸载指定的第三方库