学习了多线程下载表情包的笔记:
原视频网站:Python多线程下载表情包
整体思路
先获取整个网站的所有页面的url
把所有页面url 和所有图片url 的list, 设置成全局变量 并且要用到全局锁。(在启动多线程时,全局变量会被同时改动,所以要加上全局锁)
用了生产者-消费者模式进行爬虫
设置生产者:循环获取当前页面的所有图片的url,添加到全局变量图片url的list
设置消费者:开始下载图片。
代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import threading
import requests
import urllib
from bs4 import BeautifulSoup
import os
# 要爬的 一个简单网站
PAGE_URL = 'http://www.doutula.com/photo/list/?page='
# 页面 url
PAGE_LIST = []
# 所有图片的 url
EMOJI_LIST = []
# 全局锁
gLock = threading.Lock()
# 循环获取所有页面的url
for i in range(1, 1334):
url = PAGE_URL + str(i)
PAGE_LIST.append(url)
# 生产者:获取图片url
def Procuder():
while True:
# 加锁
gLock.acquire()
if len(PAGE_LIST) == 0:
# 解锁
gLock.release()
break
else:
page_url = PAGE_LIST.pop(0)
gLock.release()
# 获得url的所有数据
response = requests.get(page_url)
content = response.content
# content = str(content)
# 解析数据 为 lxml
soup = BeautifulSoup(content, 'lxml')
# 根据class找到img的标签
imagelist = soup.find_all('img', attrs={'class': 'img-responsive lazy image_dta'})
#
gLock.acquire()
for i in imagelist:
url = i['data-original']
# 有的图片的url后缀是:xxx.jpg!data
if url.endswith('!dta'):
url = url[:-4]
EMOJI_LIST.append(url)
gLock.release()
# 消费者:下载图片
def Customer():
while True:
gLock.acquire()
if len(EMOJI_LIST) == 0:
gLock.release()
continue
else:
url = EMOJI_LIST.pop(0)
gLock.release()
# 把url根据'/' 拆分成多个元素
split_list = url.split('/')
# 最后一个就是 图片的名称
filename = split_list.pop()
# filename = filename[:-4]
# 设置现在路径 为当前文件夹下的 images 文件夹
path = os.path.join('images', filename)
# 开始 下载
print filename
# 自带的下载方法
urllib.urlretrieve(url, filename=path)
def main():
# 两个生产者 爬图片url
for x in range(2):
th = threading.Thread(target=Procuder)
th.start()
# 三个消费者 下载图片
for x in range(3):
th = threading.Thread(target=Customer)
th.start()
if __name__ == "__main__":
main()
原网站图片的标签:
最后:
有可能会报错:Connection reset by peer;
百度了一下是①:服务器的并发连接数超过了其承载量,服务器会将其中一些连接Down掉;
②:客户关掉了浏览器,而服务器还在给客户端发送数据;
③:浏览器端按了Stop
PS:估计是网络的问题,我在测试的时候 有时候是没有报错的。。。(ಥ _ ಥ)