进程
进程: 运行中的程序. 每次我们执行一个程序, 咱们的操作系统对自动的为这个程序准备一些必要的资源(例如, 分配内存, 创建一个能够执行的线程
一个公司能创造的价值毕竟是有限的. 怎么办? 开分公司啊. 此所谓多进程.
python中常见的进程间通信方式主要是队列(Queue)和管道(Pipe)
这里讲queue
多进程在爬虫中的应用
比如, 如果遇到图片抓取的时候, 我们知道图片在一般都在网页的img标签中src属性存放的是图片的下载地址.
此时我们可以采用多进程的方案来实现,
一个负责疯狂扫图片下载地址.
另一个进程只负责下载图片.
通过队列把解析URL进程得到的URL,传递给下载进程进行下载
这个就有点像 生产者和消费者的概念
#!/usr/bin/python
import requests
from concurrent.futures.thread import ThreadPoolExecutor
from bs4 import BeautifulSoup
from urllib import parse
from multiprocessing import Process, Queue
# 可以使用多进程处理以下任务
# 进程1从图片网站中提取到图片的下载路径
# 进程2下载图片
def get_all_images_src(link, q):
response = requests.get(link)
response.encoding = 'gbk'
soup = BeautifulSoup(response.text, 'lxml')
a_list = soup.find('div', attrs={'class': 'list'}).find_all('a')
for a in a_list:
if a['href'] == 'http://pic.netbian.com/':
continue
href = a['href']
href = parse.urljoin(link, href) # 因为解析到的可能是不完成的子页面的url,那就可以用urljoin去处理,获得完整的url地址
response = requests.get(href)
response.encoding = 'gbk'
sub_soup = BeautifulSoup(response.text, 'lxml')
img_soup = sub_soup.find('div', attrs={'class': 'pic'}).find('img')
images_src = img_soup['src']
images_name = img_soup['title']
content = images_name + "#" + images_src
q.put(content)
q.put('木有了')
# 这个就是解析出来图片的src,给装到队列里去,当都装完了,就写一句木有了。
# 多进程通信下载的方法,这个里面就是拿到上面的队列,用get() 来获取到队列里面的东西,循环获取,当等于 木有了 就退出循环 因为没东西了,然后去解析、去下载就完事了
def download_images(q):
while True:
images_info = q.get()
if images_info == '木有了':
break
images_info_list = images_info.split('#')
response = requests.get(images_info_list[1])
with open('水果图片/' + images_info_list[0] + ".jpg", 'wb') as file_object:
file_object.write(response.content)
if __name__ == '__main__':
url = 'http://www.netbian.com/shuiguo/'
queue = Queue() # 在主进程创建队列
# 通过传参保障两个进程通信是同一个队列
p1 = Process(target=get_all_images_src, args=(url, queue))
p2 = Process(target=download_images, args=(queue,)) # 多进程
p1.start()
p2.start()