多线程爬取表情包

本例通过多线程爬取http://www.doutula.com网站来讲解如何让使用多线程进行爬取。

首先打开这个网站,点击最新表情:

                                                           

然后我们只需要找出最新表情相关的规律,比如我们点击一下第二页,url就变成了http://www.doutula.com/photo/list/?page=2,因此第几页page就等于几。

然后就要找出在一页当中这些表情是存储在哪里,先来看一下不用多线程的程序:

import requests
import os
from bs4 import BeautifulSoup

def download_img(page):
    response = requests.get('http://www.doutula.com/photo/list/?page={}'.format(page))
    text = response.text
    soup = BeautifulSoup(text,'lxml')
    div = soup.find_all('div',class_ = "page-content text-center")[0]
    imgs = div.find_all('img')
    for img in imgs:
        try:
            name = img.attrs['alt']#获取img标签的alt属性值,也就是名字
        except KeyError:
            pass
        try :
            img_url = img.attrs['data-backup']
        except KeyError:
            pass
        try:
            R = requests.get(img_url)
        except UnboundLocalError:
            pass
        try:
            with open('图片1/{}.jpg'.format(name),'wb') as f:
                f.write(R.content)
        except:
            pass

if __name__ == '__main__':
    if not os.path.exists('图片1'):
        os.mkdir('图片1')
    for i in range(2000):
        download_img(i+1)

如果是用多线程,就用一下结构:

                              

首先在主程序当中吧每一个待爬取页面的url定义好,然后生产者就从url队列当中去获取每一个url,再提取出每一个图片的url,拿到这些url以后再把url添加到全局的队列当中,这个队列是专门用来存储每个表情的url的,存储完了以后再使用消费者从这个队列当中去取出每个表情的url,然后下载到本地。

下面是其完整代码:

import requests
import os
from bs4 import BeautifulSoup
from queue import Queue
import threading

#定义生产者类,在创建生产者线程的时候就把两个队列传到这里面来
class Procuder(threading.Thread):
    def __init__(self,page_queue,img_queue,*args,**kwargs):#*args,**kwargs代表包括任意参数
        super(Procuder,self).__init__(*args,**kwargs)
        self.page_queue = page_queue
        self.img_queue = img_queue
    #用于解析url
    def run(self):
        #因为每一个线程都需要不断地去从页面队列当中去取url来解析
        while True:
            #为了避免生产者线程一直处于死循环状态,也就是当把url解析完毕时就应该停止了。当队列为空时退出循环
            if self.page_queue.empty():
                break
            url = self.page_queue.get()
            #拿到url后就获取我们想要的图片的url
            self.parse_page(url)#去解析每一页的url

    def parse_page(self,url):
        response = requests.get(url)
        text = response.text
        soup = BeautifulSoup(text,'lxml')
        div = soup.find_all('div',class_ = "page-content text-center")[0]
        imgs = div.find_all('img')
        for img in imgs:
            try:
                name = img.attrs['alt']#获取img标签的alt属性值,也就是名字
            except KeyError:
                pass
            try :
                img_url = img.attrs['data-backup']
            except KeyError:
                pass
            #拿到每个图片的名称和链接以后就要添加到队列当中
            try:
                self.img_queue.put((name,img_url))#传一个元组进去
            except:
                pass

#消费者
class Consumer(threading.Thread):
    def __init__(self,page_queue,img_queue,*args,**kwargs):#*args,**kwargs代表包括任意参数
        super(Consumer,self).__init__(*args,**kwargs)
        self.page_queue = page_queue
        self.img_queue = img_queue
    #不断地从img_queue里面取出url然后下载下来
    def run(self):
        while True:
            if self.img_queue.empty() and self.page_queue.empty():
                break
            filename,img_url = self.img_queue.get()#因为返回的是一个元组
            try:
                R = requests.get(img_url)
            except UnboundLocalError:
                pass
            try:
                with open('图片2/{}.jpg'.format(filename), 'wb') as f:
                    f.write(R.content)
                print('{}下载完成'.format(filename))
            except:
                pass

if __name__ == '__main__':
    #定义两个队列
    page_queue = Queue(100)#100个页面的url队列
    img_queue = Queue(1000)#图片的url
    if not os.path.exists('图片2'):
        os.mkdir('图片2')
    for i in range(100):
        url = 'http://www.doutula.com/photo/list/?page={}'.format(i+1)
        page_queue.put(url)#将每一页的url添加进去
        #然后创建生产者,把页面请求下来再获取到每个表情的url
    for x in range(5):#创建5个生产者
        t = Procuder(page_queue,img_queue)
        t.start()
    for x in range(5):#创建5个消费者
        t = Consumer(page_queue,img_queue)
        t.start()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值