tsvico的博客

好的代码像粥一样,都是用时间熬出来的

python爬虫入门到进阶(七)

多线程抓取表情包

image

用的新浪的图床,不用顾虑表情包网站服务器压力的问题,可以实验操作一下

其他网站还请手下留情,尽量不要用多线程爬别人网站,学习的目的不是破坏

image

正文开始

首先初始化锁

1
gLock = threading.Lock()

创建一个数组存放表情包链接地址,名字

1
2
3
FACE_URL_LIST = []
#名字
FACE_NAME_LIST = []

同上一个单线程的demo,先保存链接

1
2
3
for x in range(1,1500):
url = BESE_PAGE_URL + str(x)
PAGE_URL_LIST.append(url)

定义一个生产者,负责从每个页面中提取表情URL

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
class Producer(threading.Thread):
def run(self):
while len(PAGE_URL_LIST) > 0:

#在访问PAGE_URL_LIST中要使用锁机制
gLock.acquire()
page_url = PAGE_URL_LIST.pop()
#使用完把锁释放,方便其他线程使用
gLock.release()
#url请求
response = requests.get(page_url)
#使用返回的数据构建besu对象

#requests对象中 response.content返回的是二进制的数值,
# response.text返回的是Unicode型的数据
# 也就是说,如果你想获取文本,可以通过.text
# 如果你想获取图片,文件可以通过 .content
soup = BeautifulSoup(response.content,'lxml')
img_list = soup.find('div',class_ = 'page-content').find_all('img',class_ = 'img-responsive lazy image_dta')

#加锁
gLock.acquire()
for img in img_list:
title = img['alt']
if len(img_list):
src = img['data-original']
else:
continue

print(title)
print(src)
# 把提取到的表情url,添加到FACE_URL_LIST中
FACE_URL_LIST.append(src)
FACE_NAME_LIST.append(title)
#释放
gLock.release()
time.sleep(0.5)

多线程相比单线程重要的是使用某种资源时要为它加锁,用完及时释放资源解锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#消费者,负责从FACE_URL_LIST中提取链接,并下载
class Consumer(threading.Thread):
def run(self):
print '%s is runing' % threading.current_thread()
while True:
#上锁
gLock.acquire()
if len(FACE_URL_LIST)==0 or len(FACE_NAME_LIST)==0:
#不管什么情况,先释放锁
gLock.release()
continue
else:
#提取数据
face_url = FACE_URL_LIST.pop()
filename = FACE_NAME_LIST.pop()
gLock.release()
z = face_url[-4:] #后缀取名

#防止名字过长出错 2018.09.05
if len(filename) > 20 :
filename = filename[:20]
path = 'images2'+ '/' +filename.strip().replace('?','')+z
urllib.urlretrieve(face_url,path)

详细作用都在注释里

最后创建多线程调用上边的函数

1
2
3
4
5
6
7
8
if __name__=='__main__':
#两个生产者线程
for x in range(2):
Producer().start()

#5个消费者
for x in range(5):
Consumer().start()

爬虫暂时告一段落

坚持原创技术分享,您的支持将鼓励我继续创作!