为了斗图,爬一爬表情包

爬取的网址:http://www.doutula.com/photo/list/?page=

本次主要是学习多线程爬虫,使用queue队列下的生产者与消费者模式。
网站分析:这个网站的构造比较简单,直接在上面的网址后面加上1表示第一页,加上2表示第二页,以此类推。数据也都可以用requests直接访问到,没有什么反爬虫的措施,但是要爬的慢一点,太快了还是会出问题。
我这里使用的多线程的方法,爬取200页的表情包。具体代码如下:
主函数:首先通过Queue模块,构建一个200的队列用于存放每一页表情包的网址,用于提取每一个表情包的网址。构建一个1000的队列用于存放每一个表情包的网址,方便下载到本地。然后使用for循环,构建200页网址,并存放进page_queue队列中。最后构建五个生产者和五个消费者,并进行启动。

def main():
    page_queue = Queue(200)
    img_queue = Queue(1000)
    url_s = "http://www.doutula.com/photo/list/?page="
    for i in range(1, 201):
        url = url_s + str(i)
        page_queue.put(url)

    for i in range(5):
        t = Producter(page_queue, img_queue)
        t.start()
    for i in range(5):
        t = Consumer(page_queue, img_queue)
        t.start()
      
if __name__ == '__main__':
    main()

生产者函数(继承Thread模块):一开始保险起见,我在构建headers请求头的时候,还是加入了很多的信息,包括User-Agent,Accept,Cookie。然后构建初始函数,并使用super来调用父类,转换对象。详细的解析,我就写在注释中了。

class Producter(threading.Thread):
    Headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36",
        "Accept": r"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
        "Cookie": "__cfduid=d8249568756fd0d224d02db36892b6a601558100044; UM_distinctid=16ad4b7a705a24-06142f93c274de-353166-144000-16ad4b7a706a56; _ga=GA1.2.859291572.1558346967; _gid=GA1.2.1511793670.1558346967; yjs_id=3c0fb66a6388207a130a52420586feb2; ctrl_time=1; XSRF-TOKEN=eyJpdiI6IjFuS2U2eEZqM1JCNFhDaUFObkpDS0E9PSIsInZhbHVlIjoidXR0bWx6UHVNWTUxdFlyWEl6THFsXC9UVUkxODRPaVVpcEIyM1NyNDJoSU96cWc1c29VcDg5VG5vTjlZblJMTlwvIiwibWFjIjoiYzg3OGRkOTQ3YWE2Nzk1YWU4ZTdlMzMyMjE4MTNiMDMzZTY0ODdkYzA0ODc5NGUwYTM5NjBkN2ZlOGVlN2JiMiJ9; doutula_session=eyJpdiI6InRod2pjNEpXQnNcL0RKYml2dGMzb2NRPT0iLCJ2YWx1ZSI6ImlaVE8yOXhVTVNoR0ZHWVRra2RsaTJieFlhVUdBZ3BZUllzdW5OZVJCWVRDT2pJckdsT2dneWdaeDdNWDhxazEiLCJtYWMiOiIwN2RhNmE0NjFhZTJjOTRmMzdhMThkZmJhNjYzNGMxYzA1M2RjYjcwZDg1NjcxMjQ0OWU3MDEyMjI5YzM0NzQ1In0%3D; CNZZDATA1256911977=1301539121-1558343450-%7C1558358613"
    }
    def __init__(self, page_queue, img_queue, *args, **kwargs):
        super(Producter, self).__init__(*args, **kwargs)
        self.page_queue = page_queue
        self.img_queue = img_queue
    def run(self):
        while True:
            if self.page_queue.empty():  #队列为空跳出循环
                break
            url = self.page_queue.get()   #从page_获取url
            self.parse_url(url)
    def parse_url(self, url):    #对获取到的url进行解析
        response = requests.get(url, headers=self.Headers)
        html = etree.HTML(response.text)
        imgs = html.xpath("//div[@class='page-content text-center']//a//img")
        for img in imgs:
            url_img = img.get("data-original")
            alt = img.get("alt")
            try:
                suffix = os.path.splitext(url_img)[1]  #使用os模块获取文件扩展名
            except:
                continue
            filename = alt + suffix
            self.img_queue.put((url_img, filename))    #将文件名和获取到的表情包的地址存放进img_queue队列中
            time.sleep(0.5)

消费者函数(继承Thread模块):初始函数的构建和生产者一样,然后使用request模块中的urlretrieve函数将表情包下载到本地。对于表情包的名字无法构成文件名的,我这里就不要了,其实页可以使用replace函数或者re模块中的sub函数进行处理。

class Consumer(threading.Thread):
    def __init__(self,page_queue, img_queue, *args, **kwargs):
        super(Consumer, self).__init__(*args, **kwargs)
        self.page_queue = page_queue
        self.img_queue = img_queue
    def run(self):
        while True:
            if self.page_queue.empty() and self.img_queue.empty():  #判断两个队列都为空则跳出循环
                break
            url_img, filename = self.img_queue.get()
            try:
                request.urlretrieve(url_img, r"C:\Users\juno\Desktop\PYTHOY\python3-reptlie\test/" + filename)
                print(filename + "下载完成")
            except FileNotFoundError:
                continue
            time.sleep(0.5)

最后是本次爬虫用到的库:

import requests
from lxml import etree
from urllib import request
import os
import time
import threading
from queue import Queue

爬取结果:
最后是爬了六千多个就没有爬了,晚上还要睡觉(⊙﹏⊙)。

你可能感兴趣的:(爬虫)